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 AUTHORS 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.
41 Relicensed by the author as detailed above.
42 */
43
44 #include <iostream>
45 #include <limits.h>
46
47 #if (defined(__GNUC__)) && (__GNUC__ < 3)
48 #include <strstream>
49 #define stringstream strstream
50 #else
51 #include <sstream>
52 #endif
53
54 using std::cerr;
55 using std::endl;
56
57 #ifndef _WIN32
58 #include <sys/time.h>
59 #endif
60
61 #include <vamp-sdk/RealTime.h>
62
63 _VAMP_SDK_PLUGSPACE_BEGIN(RealTime.cpp)
64
65 namespace Vamp {
66
67 // A RealTime consists of two ints that must be at least 32 bits each.
68 // A signed 32-bit int can store values exceeding +/- 2 billion. This
69 // means we can safely use our lower int for nanoseconds, as there are
70 // 1 billion nanoseconds in a second and we need to handle double that
71 // because of the implementations of addition etc that we use.
72 //
73 // The maximum valid RealTime on a 32-bit system is somewhere around
74 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
75
76 #define ONE_BILLION 1000000000
77
RealTime(int s,int n)78 RealTime::RealTime(int s, int n) :
79 sec(s), nsec(n)
80 {
81 while (nsec <= -ONE_BILLION && sec > INT_MIN) { nsec += ONE_BILLION; --sec; }
82 while (nsec >= ONE_BILLION && sec < INT_MAX) { nsec -= ONE_BILLION; ++sec; }
83 while (nsec > 0 && sec < 0) { nsec -= ONE_BILLION; ++sec; }
84 while (nsec < 0 && sec > 0) { nsec += ONE_BILLION; --sec; }
85 }
86
87 RealTime
fromSeconds(double sec)88 RealTime::fromSeconds(double sec)
89 {
90 if (sec != sec) { // NaN
91 cerr << "ERROR: NaN/Inf passed to Vamp::RealTime::fromSeconds" << endl;
92 return RealTime::zeroTime;
93 } else if (sec >= 0) {
94 return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
95 } else {
96 return -fromSeconds(-sec);
97 }
98 }
99
100 RealTime
fromMilliseconds(int msec)101 RealTime::fromMilliseconds(int msec)
102 {
103 return RealTime(msec / 1000, (msec % 1000) * 1000000);
104 }
105
106 #ifndef _WIN32
107 RealTime
fromTimeval(const struct timeval & tv)108 RealTime::fromTimeval(const struct timeval &tv)
109 {
110 return RealTime(int(tv.tv_sec), int(tv.tv_usec * 1000));
111 }
112 #endif
113
operator <<(std::ostream & out,const RealTime & rt)114 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
115 {
116 if (rt < RealTime::zeroTime) {
117 out << "-";
118 } else {
119 out << " ";
120 }
121
122 int s = (rt.sec < 0 ? -rt.sec : rt.sec);
123 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
124
125 out << s << ".";
126
127 int nn(n);
128 if (nn == 0) out << "00000000";
129 else while (nn < (ONE_BILLION / 10)) {
130 out << "0";
131 nn *= 10;
132 }
133
134 out << n << "R";
135 return out;
136 }
137
138 std::string
toString() const139 RealTime::toString() const
140 {
141 std::stringstream out;
142 out << *this;
143
144 std::string s = out.str();
145
146 // remove trailing R
147 return s.substr(0, s.length() - 1);
148 }
149
150 std::string
toText(bool fixedDp) const151 RealTime::toText(bool fixedDp) const
152 {
153 if (*this < RealTime::zeroTime) return "-" + (-*this).toText(fixedDp);
154
155 std::stringstream out;
156
157 if (sec >= 3600) {
158 out << (sec / 3600) << ":";
159 }
160
161 if (sec >= 60) {
162 int minutes = (sec % 3600) / 60;
163 if (sec >= 3600 && minutes < 10) out << "0";
164 out << minutes << ":";
165 }
166
167 if (sec >= 10) {
168 out << ((sec % 60) / 10);
169 }
170
171 out << (sec % 10);
172
173 int ms = msec();
174
175 if (ms != 0) {
176 out << ".";
177 out << (ms / 100);
178 ms = ms % 100;
179 if (ms != 0) {
180 out << (ms / 10);
181 ms = ms % 10;
182 } else if (fixedDp) {
183 out << "0";
184 }
185 if (ms != 0) {
186 out << ms;
187 } else if (fixedDp) {
188 out << "0";
189 }
190 } else if (fixedDp) {
191 out << ".000";
192 }
193
194 std::string s = out.str();
195
196 return s;
197 }
198
199 RealTime
operator /(int d) const200 RealTime::operator/(int d) const
201 {
202 int secdiv = sec / d;
203 int secrem = sec % d;
204
205 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
206
207 return RealTime(secdiv, int(nsecdiv + 0.5));
208 }
209
210 double
operator /(const RealTime & r) const211 RealTime::operator/(const RealTime &r) const
212 {
213 double lTotal = double(sec) * ONE_BILLION + double(nsec);
214 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
215
216 if (rTotal == 0) return 0.0;
217 else return lTotal/rTotal;
218 }
219
220 long
realTime2Frame(const RealTime & time,unsigned int sampleRate)221 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
222 {
223 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
224 double s = time.sec + double(time.nsec) / ONE_BILLION;
225 return long(s * sampleRate + 0.5);
226 }
227
228 RealTime
frame2RealTime(long frame,unsigned int sampleRate)229 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
230 {
231 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
232
233 int sec = int(frame / long(sampleRate));
234 frame -= sec * long(sampleRate);
235 int nsec = (int)((double(frame) / double(sampleRate)) * ONE_BILLION + 0.5);
236 // Use ctor here instead of setting data members directly to
237 // ensure nsec > ONE_BILLION is handled properly. It's extremely
238 // unlikely, but not impossible.
239 return RealTime(sec, nsec);
240 }
241
242 const RealTime RealTime::zeroTime(0,0);
243
244 }
245
246 _VAMP_SDK_PLUGSPACE_END(RealTime.cpp)
247
248
249
250