d3c436478518360ed5dd2e88b71ce3f23eaf79ec
[ardour.git] / libs / vamp-sdk / src / vamp-sdk / RealTime.cpp
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
46 #if (__GNUC__ < 3)
47 #include <strstream>
48 #define stringstream strstream
49 #else
50 #include <sstream>
51 #endif
52
53 using std::cerr;
54 using std::endl;
55
56 #ifndef _WIN32
57 #include <sys/time.h>
58 #endif
59
60 #include <vamp-sdk/RealTime.h>
61
62 _VAMP_SDK_PLUGSPACE_BEGIN(RealTime.cpp)
63
64 namespace Vamp {
65
66 // A RealTime consists of two ints that must be at least 32 bits each.
67 // A signed 32-bit int can store values exceeding +/- 2 billion.  This
68 // means we can safely use our lower int for nanoseconds, as there are
69 // 1 billion nanoseconds in a second and we need to handle double that
70 // because of the implementations of addition etc that we use.
71 //
72 // The maximum valid RealTime on a 32-bit system is somewhere around
73 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
74
75 #define ONE_BILLION 1000000000
76
77 RealTime::RealTime(int s, int n) :
78     sec(s), nsec(n)
79 {
80     if (sec == 0) {
81         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
82         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
83     } else if (sec < 0) {
84         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
85         while (nsec > 0)             { nsec -= ONE_BILLION; ++sec; }
86     } else { 
87         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
88         while (nsec < 0)             { nsec += ONE_BILLION; --sec; }
89     }
90 }
91
92 RealTime
93 RealTime::fromSeconds(double sec)
94 {
95     return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
96 }
97
98 RealTime
99 RealTime::fromMilliseconds(int msec)
100 {
101     return RealTime(msec / 1000, (msec % 1000) * 1000000);
102 }
103
104 #ifndef _WIN32
105 RealTime
106 RealTime::fromTimeval(const struct timeval &tv)
107 {
108     return RealTime(tv.tv_sec, tv.tv_usec * 1000);
109 }
110 #endif
111
112 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
113 {
114     if (rt < RealTime::zeroTime) {
115         out << "-";
116     } else {
117         out << " ";
118     }
119
120     int s = (rt.sec < 0 ? -rt.sec : rt.sec);
121     int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
122
123     out << s << ".";
124
125     int nn(n);
126     if (nn == 0) out << "00000000";
127     else while (nn < (ONE_BILLION / 10)) {
128         out << "0";
129         nn *= 10;
130     }
131     
132     out << n << "R";
133     return out;
134 }
135
136 std::string
137 RealTime::toString() const
138 {
139     std::stringstream out;
140     out << *this;
141     
142 #if (__GNUC__ < 3)
143     out << std::ends;
144 #endif
145
146     std::string s = out.str();
147
148     // remove trailing R
149     return s.substr(0, s.length() - 1);
150 }
151
152 std::string
153 RealTime::toText(bool fixedDp) const
154 {
155     if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
156
157     std::stringstream out;
158
159     if (sec >= 3600) {
160         out << (sec / 3600) << ":";
161     }
162
163     if (sec >= 60) {
164         out << (sec % 3600) / 60 << ":";
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 #if (__GNUC__ < 3)
195     out << std::ends;
196 #endif
197
198     std::string s = out.str();
199
200     return s;
201 }
202
203
204 RealTime
205 RealTime::operator/(int d) const
206 {
207     int secdiv = sec / d;
208     int secrem = sec % d;
209
210     double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
211     
212     return RealTime(secdiv, int(nsecdiv + 0.5));
213 }
214
215 double 
216 RealTime::operator/(const RealTime &r) const
217 {
218     double lTotal = double(sec) * ONE_BILLION + double(nsec);
219     double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
220     
221     if (rTotal == 0) return 0.0;
222     else return lTotal/rTotal;
223 }
224
225 long
226 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
227 {
228     if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
229     double s = time.sec + double(time.nsec + 1) / 1000000000.0;
230     return long(s * sampleRate);
231 }
232
233 RealTime
234 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
235 {
236     if (frame < 0) return -frame2RealTime(-frame, sampleRate);
237
238     RealTime rt;
239     rt.sec = frame / long(sampleRate);
240     frame -= rt.sec * long(sampleRate);
241     rt.nsec = (int)(((double(frame) * 1000000.0) / sampleRate) * 1000.0);
242     return rt;
243 }
244
245 const RealTime RealTime::zeroTime(0,0);
246
247 }
248
249 _VAMP_SDK_PLUGSPACE_END(RealTime.cpp)
250
251
252