RealTime.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     
00008     This program is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU General Public License as
00010     published by the Free Software Foundation; either version 2 of the
00011     License, or (at your option) any later version.  See the file
00012     COPYING included with this distribution for more information.
00013 */
00014 
00015 /*
00016    This is a modified version of a source file from the 
00017    Rosegarden MIDI and audio sequencer and notation editor.
00018    This file copyright 2000-2006 Chris Cannam.
00019 */
00020 
00021 #include <iostream>
00022 
00023 #if (__GNUC__ < 3)
00024 #include <strstream>
00025 #define stringstream strstream
00026 #else
00027 #include <sstream>
00028 #endif
00029 
00030 using std::cerr;
00031 using std::endl;
00032 
00033 #include "RealTime.h"
00034 #include "sys/time.h"
00035 
00036 // A RealTime consists of two ints that must be at least 32 bits each.
00037 // A signed 32-bit int can store values exceeding +/- 2 billion.  This
00038 // means we can safely use our lower int for nanoseconds, as there are
00039 // 1 billion nanoseconds in a second and we need to handle double that
00040 // because of the implementations of addition etc that we use.
00041 //
00042 // The maximum valid RealTime on a 32-bit system is somewhere around
00043 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
00044 
00045 #define ONE_BILLION 1000000000
00046 
00047 RealTime::RealTime(int s, int n) :
00048     sec(s), nsec(n)
00049 {
00050     if (sec == 0) {
00051         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
00052         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
00053     } else if (sec < 0) {
00054         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
00055         while (nsec > 0)             { nsec -= ONE_BILLION; ++sec; }
00056     } else { 
00057         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
00058         while (nsec < 0)             { nsec += ONE_BILLION; --sec; }
00059     }
00060 }
00061 
00062 RealTime
00063 RealTime::fromSeconds(double sec)
00064 {
00065     return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
00066 }
00067 
00068 RealTime
00069 RealTime::fromMilliseconds(int msec)
00070 {
00071     return RealTime(msec / 1000, (msec % 1000) * 1000000);
00072 }
00073 
00074 RealTime
00075 RealTime::fromTimeval(const struct timeval &tv)
00076 {
00077     return RealTime(tv.tv_sec, tv.tv_usec * 1000);
00078 }
00079 
00080 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
00081 {
00082     if (rt < RealTime::zeroTime) {
00083         out << "-";
00084     } else {
00085         out << " ";
00086     }
00087 
00088     int s = (rt.sec < 0 ? -rt.sec : rt.sec);
00089     int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
00090 
00091     out << s << ".";
00092 
00093     int nn(n);
00094     if (nn == 0) out << "00000000";
00095     else while (nn < (ONE_BILLION / 10)) {
00096         out << "0";
00097         nn *= 10;
00098     }
00099     
00100     out << n << "R";
00101     return out;
00102 }
00103 
00104 std::string
00105 RealTime::toString(bool align) const
00106 {
00107     std::stringstream out;
00108     out << *this;
00109     
00110 #if (__GNUC__ < 3)
00111     out << std::ends;
00112 #endif
00113 
00114     std::string s = out.str();
00115 
00116     if (!align && *this >= RealTime::zeroTime) {
00117         // remove leading " "
00118         s = s.substr(1, s.length() - 1);
00119     }
00120 
00121     // remove trailing R
00122     return s.substr(0, s.length() - 1);
00123 }
00124 
00125 RealTime
00126 RealTime::fromString(std::string s)
00127 {
00128     bool negative = false;
00129     bool faulty = false;
00130     bool section = 0;
00131     std::string ssec, snsec;
00132 
00133     for (size_t i = 0; i < s.length(); ++i) {
00134 
00135         char c = s[i];
00136         if (isspace(c)) continue;
00137 
00138         if (section == 0) {
00139 
00140             if (c == '-') negative = true;
00141             else if (isdigit(c)) { section = 1; ssec += c; }
00142             else if (c == '.') section = 2;
00143             else break;
00144 
00145         } else if (section == 1) {
00146 
00147             if (c == '.') section = 2;
00148             else if (isdigit(c)) ssec += c;
00149             else break;
00150 
00151         } else if (section == 2) {
00152 
00153             if (isdigit(c)) snsec += c;
00154             else break;
00155         }
00156     }
00157 
00158     while (snsec.length() < 8) snsec += '0';
00159 
00160     int sec = atoi(ssec.c_str());
00161     int nsec = atoi(snsec.c_str());
00162     if (negative) sec = -sec;
00163 
00164     std::cerr << "RealTime::fromString: string " << s << " -> "
00165               << sec << " sec, " << nsec << " nsec" << std::endl;
00166 
00167     return RealTime(sec, nsec);
00168 }
00169 
00170 std::string
00171 RealTime::toText(bool fixedDp) const
00172 {
00173     if (*this < RealTime::zeroTime) return "-" + (-*this).toText(fixedDp);
00174 
00175     std::stringstream out;
00176 
00177     if (sec >= 3600) {
00178         out << (sec / 3600) << ":";
00179     }
00180 
00181     if (sec >= 60) {
00182         out << (sec % 3600) / 60 << ":";
00183     }
00184 
00185     if (sec >= 10) {
00186         out << ((sec % 60) / 10);
00187     }
00188 
00189     out << (sec % 10);
00190     
00191     int ms = msec();
00192 
00193     if (ms != 0) {
00194         out << ".";
00195         out << (ms / 100);
00196         ms = ms % 100;
00197         if (ms != 0) {
00198             out << (ms / 10);
00199             ms = ms % 10;
00200         } else if (fixedDp) {
00201             out << "0";
00202         }
00203         if (ms != 0) {
00204             out << ms;
00205         } else if (fixedDp) {
00206             out << "0";
00207         }
00208     } else if (fixedDp) {
00209         out << ".000";
00210     }
00211         
00212 #if (__GNUC__ < 3)
00213     out << std::ends;
00214 #endif
00215 
00216     std::string s = out.str();
00217 
00218     return s;
00219 }
00220 
00221 std::string
00222 RealTime::toSecText() const
00223 {
00224     if (*this < RealTime::zeroTime) return "-" + (-*this).toSecText();
00225 
00226     std::stringstream out;
00227 
00228     if (sec >= 3600) {
00229         out << (sec / 3600) << ":";
00230     }
00231 
00232     if (sec >= 60) {
00233         out << (sec % 3600) / 60 << ":";
00234     }
00235 
00236     if (sec >= 10) {
00237         out << ((sec % 60) / 10);
00238     }
00239 
00240     out << (sec % 10);
00241     
00242     if (sec < 60) {
00243         out << "s";
00244     }
00245 
00246         
00247 #if (__GNUC__ < 3)
00248     out << std::ends;
00249 #endif
00250 
00251     std::string s = out.str();
00252 
00253     return s;
00254 }
00255 
00256 RealTime
00257 RealTime::operator*(int m) const
00258 {
00259     double t = (double(nsec) / ONE_BILLION) * m;
00260     t += sec * m;
00261     return fromSeconds(t);
00262 }
00263 
00264 RealTime
00265 RealTime::operator/(int d) const
00266 {
00267     int secdiv = sec / d;
00268     int secrem = sec % d;
00269 
00270     double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
00271     
00272     return RealTime(secdiv, int(nsecdiv + 0.5));
00273 }
00274 
00275 RealTime
00276 RealTime::operator*(double m) const
00277 {
00278     double t = (double(nsec) / ONE_BILLION) * m;
00279     t += sec * m;
00280     return fromSeconds(t);
00281 }
00282 
00283 RealTime
00284 RealTime::operator/(double d) const
00285 {
00286     double t = (double(nsec) / ONE_BILLION) / d;
00287     t += sec / d;
00288     return fromSeconds(t);
00289 }
00290 
00291 double 
00292 RealTime::operator/(const RealTime &r) const
00293 {
00294     double lTotal = double(sec) * ONE_BILLION + double(nsec);
00295     double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
00296     
00297     if (rTotal == 0) return 0.0;
00298     else return lTotal/rTotal;
00299 }
00300 
00301 long
00302 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
00303 {
00304     if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
00305 
00306     // We like integers.  The last term is always zero unless the
00307     // sample rate is greater than 1MHz, but hell, you never know...
00308 
00309     long frame =
00310         time.sec * sampleRate +
00311         (time.msec() * sampleRate) / 1000 +
00312         ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
00313         ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
00314 
00315     return frame;
00316 }
00317 
00318 RealTime
00319 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
00320 {
00321     if (frame < 0) return -frame2RealTime(-frame, sampleRate);
00322 
00323     RealTime rt;
00324     rt.sec = frame / long(sampleRate);
00325     frame -= rt.sec * long(sampleRate);
00326     rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
00327     return rt;
00328 }
00329 
00330 const RealTime RealTime::zeroTime(0,0);
00331 

Generated on Wed Feb 20 15:45:27 2008 for SonicVisualiser by  doxygen 1.5.1