annotate base/RealTime.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents 87495ac7710a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7
lbajardsilogic@0 8 This program is free software; you can redistribute it and/or
lbajardsilogic@0 9 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 10 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 11 License, or (at your option) any later version. See the file
lbajardsilogic@0 12 COPYING included with this distribution for more information.
lbajardsilogic@0 13 */
lbajardsilogic@0 14
lbajardsilogic@0 15 /*
lbajardsilogic@0 16 This is a modified version of a source file from the
lbajardsilogic@0 17 Rosegarden MIDI and audio sequencer and notation editor.
lbajardsilogic@0 18 This file copyright 2000-2006 Chris Cannam.
lbajardsilogic@0 19 */
lbajardsilogic@0 20
lbajardsilogic@0 21 #include <iostream>
lbajardsilogic@0 22
lbajardsilogic@0 23 #if (__GNUC__ < 3)
lbajardsilogic@0 24 #include <strstream>
lbajardsilogic@0 25 #define stringstream strstream
lbajardsilogic@0 26 #else
lbajardsilogic@0 27 #include <sstream>
lbajardsilogic@0 28 #endif
lbajardsilogic@0 29
lbajardsilogic@0 30 using std::cerr;
lbajardsilogic@0 31 using std::endl;
lbajardsilogic@0 32
lbajardsilogic@0 33 #include "RealTime.h"
lbajardsilogic@0 34 #ifdef USE_VC
lbajardsilogic@0 35 #include "winsock2.h"
lbajardsilogic@0 36 #else
lbajardsilogic@0 37 #include "sys/time.h"
lbajardsilogic@0 38 #endif
lbajardsilogic@0 39 // A RealTime consists of two ints that must be at least 32 bits each.
lbajardsilogic@0 40 // A signed 32-bit int can store values exceeding +/- 2 billion. This
lbajardsilogic@0 41 // means we can safely use our lower int for nanoseconds, as there are
lbajardsilogic@0 42 // 1 billion nanoseconds in a second and we need to handle double that
lbajardsilogic@0 43 // because of the implementations of addition etc that we use.
lbajardsilogic@0 44 //
lbajardsilogic@0 45 // The maximum valid RealTime on a 32-bit system is somewhere around
lbajardsilogic@0 46 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
lbajardsilogic@0 47
lbajardsilogic@0 48 #define ONE_BILLION 1000000000
lbajardsilogic@0 49
lbajardsilogic@0 50 RealTime::RealTime(int s, int n) :
lbajardsilogic@0 51 sec(s), nsec(n)
lbajardsilogic@0 52 {
lbajardsilogic@0 53 if (sec == 0) {
lbajardsilogic@0 54 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
lbajardsilogic@0 55 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
lbajardsilogic@0 56 } else if (sec < 0) {
lbajardsilogic@0 57 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
lbajardsilogic@0 58 while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
lbajardsilogic@0 59 } else {
lbajardsilogic@0 60 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
lbajardsilogic@0 61 while (nsec < 0) { nsec += ONE_BILLION; --sec; }
lbajardsilogic@0 62 }
lbajardsilogic@0 63 }
lbajardsilogic@0 64
lbajardsilogic@0 65 RealTime
lbajardsilogic@0 66 RealTime::fromSeconds(double sec)
lbajardsilogic@0 67 {
lbajardsilogic@0 68 return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
lbajardsilogic@0 69 }
lbajardsilogic@0 70
lbajardsilogic@0 71 RealTime
lbajardsilogic@0 72 RealTime::fromMilliseconds(int msec)
lbajardsilogic@0 73 {
lbajardsilogic@0 74 return RealTime(msec / 1000, (msec % 1000) * 1000000);
lbajardsilogic@0 75 }
lbajardsilogic@0 76
lbajardsilogic@0 77 RealTime
lbajardsilogic@0 78 RealTime::fromTimeval(const struct timeval &tv)
lbajardsilogic@0 79 {
lbajardsilogic@0 80 return RealTime(tv.tv_sec, tv.tv_usec * 1000);
lbajardsilogic@0 81 }
lbajardsilogic@0 82
lbajardsilogic@0 83 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
lbajardsilogic@0 84 {
lbajardsilogic@0 85 if (rt < RealTime::zeroTime) {
lbajardsilogic@0 86 out << "-";
lbajardsilogic@0 87 } else {
lbajardsilogic@0 88 out << " ";
lbajardsilogic@0 89 }
lbajardsilogic@0 90
lbajardsilogic@0 91 int s = (rt.sec < 0 ? -rt.sec : rt.sec);
lbajardsilogic@0 92 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
lbajardsilogic@0 93
lbajardsilogic@0 94 out << s << ".";
lbajardsilogic@0 95
lbajardsilogic@0 96 int nn(n);
lbajardsilogic@0 97 if (nn == 0) out << "00000000";
lbajardsilogic@0 98 else while (nn < (ONE_BILLION / 10)) {
lbajardsilogic@0 99 out << "0";
lbajardsilogic@0 100 nn *= 10;
lbajardsilogic@0 101 }
lbajardsilogic@0 102
lbajardsilogic@0 103 out << n << "R";
lbajardsilogic@0 104 return out;
lbajardsilogic@0 105 }
lbajardsilogic@0 106
lbajardsilogic@0 107 std::string
lbajardsilogic@0 108 RealTime::toString(bool align) const
lbajardsilogic@0 109 {
lbajardsilogic@0 110 std::stringstream out;
lbajardsilogic@0 111 out << *this;
lbajardsilogic@0 112
lbajardsilogic@0 113 #if (__GNUC__ < 3)
lbajardsilogic@0 114 out << std::ends;
lbajardsilogic@0 115 #endif
lbajardsilogic@0 116
lbajardsilogic@0 117 std::string s = out.str();
lbajardsilogic@0 118
lbajardsilogic@0 119 if (!align && *this >= RealTime::zeroTime) {
lbajardsilogic@0 120 // remove leading " "
lbajardsilogic@0 121 s = s.substr(1, s.length() - 1);
lbajardsilogic@0 122 }
lbajardsilogic@0 123
lbajardsilogic@0 124 // remove trailing R
lbajardsilogic@0 125 return s.substr(0, s.length() - 1);
lbajardsilogic@0 126 }
lbajardsilogic@0 127
lbajardsilogic@0 128 std::string
lbajardsilogic@0 129 RealTime::toText(bool fixedDp) const
lbajardsilogic@0 130 {
lbajardsilogic@0 131 if (*this < RealTime::zeroTime) return "-" + (-*this).toText(fixedDp);
lbajardsilogic@0 132
lbajardsilogic@0 133 std::stringstream out;
lbajardsilogic@0 134
lbajardsilogic@0 135 if (sec >= 3600) {
lbajardsilogic@0 136 out << (sec / 3600) << ":";
lbajardsilogic@0 137 }
lbajardsilogic@0 138
lbajardsilogic@0 139 if (sec >= 60) {
lbajardsilogic@0 140 out << (sec % 3600) / 60 << ":";
lbajardsilogic@0 141 }
lbajardsilogic@0 142
lbajardsilogic@0 143 if (sec >= 10) {
lbajardsilogic@0 144 out << ((sec % 60) / 10);
lbajardsilogic@0 145 }
lbajardsilogic@0 146
lbajardsilogic@0 147 out << (sec % 10);
lbajardsilogic@0 148
lbajardsilogic@0 149 int ms = msec();
lbajardsilogic@0 150
lbajardsilogic@0 151 if (ms != 0) {
lbajardsilogic@0 152 out << ".";
lbajardsilogic@0 153 out << (ms / 100);
lbajardsilogic@0 154 ms = ms % 100;
lbajardsilogic@0 155 if (ms != 0) {
lbajardsilogic@0 156 out << (ms / 10);
lbajardsilogic@0 157 ms = ms % 10;
lbajardsilogic@0 158 } else if (fixedDp) {
lbajardsilogic@0 159 out << "0";
lbajardsilogic@0 160 }
lbajardsilogic@0 161 if (ms != 0) {
lbajardsilogic@0 162 out << ms;
lbajardsilogic@0 163 } else if (fixedDp) {
lbajardsilogic@0 164 out << "0";
lbajardsilogic@0 165 }
lbajardsilogic@0 166 } else if (fixedDp) {
lbajardsilogic@0 167 out << ".000";
lbajardsilogic@0 168 }
lbajardsilogic@0 169
lbajardsilogic@0 170 #if (__GNUC__ < 3)
lbajardsilogic@0 171 out << std::ends;
lbajardsilogic@0 172 #endif
lbajardsilogic@0 173
lbajardsilogic@0 174 std::string s = out.str();
lbajardsilogic@0 175
lbajardsilogic@0 176 return s;
lbajardsilogic@0 177 }
lbajardsilogic@0 178
lbajardsilogic@0 179 std::string
lbajardsilogic@0 180 RealTime::toSecText() const
lbajardsilogic@0 181 {
lbajardsilogic@0 182 if (*this < RealTime::zeroTime) return "-" + (-*this).toSecText();
lbajardsilogic@0 183
lbajardsilogic@0 184 std::stringstream out;
lbajardsilogic@0 185
lbajardsilogic@0 186 if (sec >= 3600) {
lbajardsilogic@0 187 out << (sec / 3600) << ":";
lbajardsilogic@0 188 }
lbajardsilogic@0 189
lbajardsilogic@0 190 if (sec >= 60) {
lbajardsilogic@0 191 out << (sec % 3600) / 60 << ":";
lbajardsilogic@0 192 }
lbajardsilogic@0 193
lbajardsilogic@0 194 if (sec >= 10) {
lbajardsilogic@0 195 out << ((sec % 60) / 10);
lbajardsilogic@0 196 }
lbajardsilogic@0 197
lbajardsilogic@0 198 out << (sec % 10);
lbajardsilogic@0 199
lbajardsilogic@0 200 if (sec < 60) {
lbajardsilogic@0 201 out << "s";
lbajardsilogic@0 202 }
lbajardsilogic@0 203
lbajardsilogic@0 204
lbajardsilogic@0 205 #if (__GNUC__ < 3)
lbajardsilogic@0 206 out << std::ends;
lbajardsilogic@0 207 #endif
lbajardsilogic@0 208
lbajardsilogic@0 209 std::string s = out.str();
lbajardsilogic@0 210
lbajardsilogic@0 211 return s;
lbajardsilogic@0 212 }
lbajardsilogic@0 213
lbajardsilogic@0 214 RealTime
lbajardsilogic@0 215 RealTime::operator*(int m) const
lbajardsilogic@0 216 {
lbajardsilogic@0 217 double t = (double(nsec) / ONE_BILLION) * m;
lbajardsilogic@0 218 t += sec * m;
lbajardsilogic@0 219 return fromSeconds(t);
lbajardsilogic@0 220 }
lbajardsilogic@0 221
lbajardsilogic@0 222 RealTime
lbajardsilogic@0 223 RealTime::operator/(int d) const
lbajardsilogic@0 224 {
lbajardsilogic@0 225 int secdiv = sec / d;
lbajardsilogic@0 226 int secrem = sec % d;
lbajardsilogic@0 227
lbajardsilogic@0 228 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
lbajardsilogic@0 229
lbajardsilogic@0 230 return RealTime(secdiv, int(nsecdiv + 0.5));
lbajardsilogic@0 231 }
lbajardsilogic@0 232
lbajardsilogic@0 233 double
lbajardsilogic@0 234 RealTime::operator/(const RealTime &r) const
lbajardsilogic@0 235 {
lbajardsilogic@0 236 double lTotal = double(sec) * ONE_BILLION + double(nsec);
lbajardsilogic@0 237 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
lbajardsilogic@0 238
lbajardsilogic@0 239 if (rTotal == 0) return 0.0;
lbajardsilogic@0 240 else return lTotal/rTotal;
lbajardsilogic@0 241 }
lbajardsilogic@0 242
lbajardsilogic@0 243 long
lbajardsilogic@0 244 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
lbajardsilogic@0 245 {
lbajardsilogic@0 246 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
lbajardsilogic@0 247
lbajardsilogic@0 248 // We like integers. The last term is always zero unless the
lbajardsilogic@0 249 // sample rate is greater than 1MHz, but hell, you never know...
lbajardsilogic@0 250
lbajardsilogic@0 251 long frame =
lbajardsilogic@0 252 time.sec * sampleRate +
lbajardsilogic@0 253 (time.msec() * sampleRate) / 1000 +
lbajardsilogic@0 254 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
lbajardsilogic@0 255 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
lbajardsilogic@0 256
lbajardsilogic@0 257 return frame;
lbajardsilogic@0 258 }
lbajardsilogic@0 259
lbajardsilogic@0 260 RealTime
lbajardsilogic@0 261 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
lbajardsilogic@0 262 {
lbajardsilogic@0 263 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
lbajardsilogic@0 264
lbajardsilogic@0 265 RealTime rt;
lbajardsilogic@90 266 if (sampleRate == 0)
lbajardsilogic@90 267 {
lbajardsilogic@90 268 rt.sec = 0;
lbajardsilogic@90 269 rt.nsec = 0;
lbajardsilogic@90 270 }
lbajardsilogic@90 271 else
lbajardsilogic@90 272 {
lbajardsilogic@90 273 rt.sec = frame / long(sampleRate);
lbajardsilogic@90 274 frame -= rt.sec * long(sampleRate);
lbajardsilogic@90 275 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
lbajardsilogic@90 276 }
lbajardsilogic@0 277 return rt;
lbajardsilogic@0 278 }
lbajardsilogic@0 279
lbajardsilogic@0 280 const RealTime RealTime::zeroTime(0,0);
lbajardsilogic@0 281