annotate base/RealTime.cpp @ 308:14e0f60435b8

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