Merge with 2.0-ongoing R2885.
[ardour.git] / libs / vamp-sdk / 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 #include "RealTime.h"
57
58 #ifndef _WIN32
59 #include <sys/time.h>
60 #endif
61
62 namespace Vamp {
63
64 // A RealTime consists of two ints that must be at least 32 bits each.
65 // A signed 32-bit int can store values exceeding +/- 2 billion.  This
66 // means we can safely use our lower int for nanoseconds, as there are
67 // 1 billion nanoseconds in a second and we need to handle double that
68 // because of the implementations of addition etc that we use.
69 //
70 // The maximum valid RealTime on a 32-bit system is somewhere around
71 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
72
73 #define ONE_BILLION 1000000000
74
75 RealTime::RealTime(int s, int n) :
76     sec(s), nsec(n)
77 {
78     if (sec == 0) {
79         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
80         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
81     } else if (sec < 0) {
82         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
83         while (nsec > 0)             { nsec -= ONE_BILLION; ++sec; }
84     } else { 
85         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
86         while (nsec < 0)             { nsec += ONE_BILLION; --sec; }
87     }
88 }
89
90 RealTime
91 RealTime::fromSeconds(double sec)
92 {
93     return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
94 }
95
96 RealTime
97 RealTime::fromMilliseconds(int msec)
98 {
99     return RealTime(msec / 1000, (msec % 1000) * 1000000);
100 }
101
102 #ifndef _WIN32
103 RealTime
104 RealTime::fromTimeval(const struct timeval &tv)
105 {
106     return RealTime(tv.tv_sec, tv.tv_usec * 1000);
107 }
108 #endif
109
110 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
111 {
112     if (rt < RealTime::zeroTime) {
113         out << "-";
114     } else {
115         out << " ";
116     }
117
118     int s = (rt.sec < 0 ? -rt.sec : rt.sec);
119     int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
120
121     out << s << ".";
122
123     int nn(n);
124     if (nn == 0) out << "00000000";
125     else while (nn < (ONE_BILLION / 10)) {
126         out << "0";
127         nn *= 10;
128     }
129     
130     out << n << "R";
131     return out;
132 }
133
134 std::string
135 RealTime::toString() const
136 {
137     std::stringstream out;
138     out << *this;
139     
140 #if (__GNUC__ < 3)
141     out << std::ends;
142 #endif
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
151 RealTime::toText(bool fixedDp) const
152 {
153     if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
154
155     std::stringstream out;
156
157     if (sec >= 3600) {
158         out << (sec / 3600) << ":";
159     }
160
161     if (sec >= 60) {
162         out << (sec % 3600) / 60 << ":";
163     }
164
165     if (sec >= 10) {
166         out << ((sec % 60) / 10);
167     }
168
169     out << (sec % 10);
170     
171     int ms = msec();
172
173     if (ms != 0) {
174         out << ".";
175         out << (ms / 100);
176         ms = ms % 100;
177         if (ms != 0) {
178             out << (ms / 10);
179             ms = ms % 10;
180         } else if (fixedDp) {
181             out << "0";
182         }
183         if (ms != 0) {
184             out << ms;
185         } else if (fixedDp) {
186             out << "0";
187         }
188     } else if (fixedDp) {
189         out << ".000";
190     }
191         
192 #if (__GNUC__ < 3)
193     out << std::ends;
194 #endif
195
196     std::string s = out.str();
197
198     return s;
199 }
200
201
202 RealTime
203 RealTime::operator/(int d) const
204 {
205     int secdiv = sec / d;
206     int secrem = sec % d;
207
208     double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
209     
210     return RealTime(secdiv, int(nsecdiv + 0.5));
211 }
212
213 double 
214 RealTime::operator/(const RealTime &r) const
215 {
216     double lTotal = double(sec) * ONE_BILLION + double(nsec);
217     double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
218     
219     if (rTotal == 0) return 0.0;
220     else return lTotal/rTotal;
221 }
222
223 long
224 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
225 {
226     if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
227
228     // We like integers.  The last term is always zero unless the
229     // sample rate is greater than 1MHz, but hell, you never know...
230
231     long frame =
232         time.sec * sampleRate +
233         (time.msec() * sampleRate) / 1000 +
234         ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
235         ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
236
237     return frame;
238 }
239
240 RealTime
241 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
242 {
243     if (frame < 0) return -frame2RealTime(-frame, sampleRate);
244
245     RealTime rt;
246     rt.sec = frame / long(sampleRate);
247     frame -= rt.sec * long(sampleRate);
248     rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
249     return rt;
250 }
251
252 const RealTime RealTime::zeroTime(0,0);
253
254 }