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     Vamp
00005 
00006     An API for audio analysis and feature extraction plugins.
00007 
00008     Centre for Digital Music, Queen Mary, University of London.
00009     Copyright 2006 Chris Cannam.
00010   
00011     Permission is hereby granted, free of charge, to any person
00012     obtaining a copy of this software and associated documentation
00013     files (the "Software"), to deal in the Software without
00014     restriction, including without limitation the rights to use, copy,
00015     modify, merge, publish, distribute, sublicense, and/or sell copies
00016     of the Software, and to permit persons to whom the Software is
00017     furnished to do so, subject to the following conditions:
00018 
00019     The above copyright notice and this permission notice shall be
00020     included in all copies or substantial portions of the Software.
00021 
00022     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00023     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00024     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00025     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
00026     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00027     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00028     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00029 
00030     Except as contained in this notice, the names of the Centre for
00031     Digital Music; Queen Mary, University of London; and Chris Cannam
00032     shall not be used in advertising or otherwise to promote the sale,
00033     use or other dealings in this Software without prior written
00034     authorization.
00035 */
00036 
00037 /*
00038    This is a modified version of a source file from the 
00039    Rosegarden MIDI and audio sequencer and notation editor.
00040    This file copyright 2000-2006 Chris Cannam.
00041    Relicensed by the author as detailed above.
00042 */
00043 
00044 #include <iostream>
00045 
00046 #if (__GNUC__ < 3)
00047 #include <strstream>
00048 #define stringstream strstream
00049 #else
00050 #include <sstream>
00051 #endif
00052 
00053 using std::cerr;
00054 using std::endl;
00055 
00056 #include "RealTime.h"
00057 
00058 #ifndef _WIN32
00059 #include <sys/time.h>
00060 #endif
00061 
00062 namespace Vamp {
00063 
00064 // A RealTime consists of two ints that must be at least 32 bits each.
00065 // A signed 32-bit int can store values exceeding +/- 2 billion.  This
00066 // means we can safely use our lower int for nanoseconds, as there are
00067 // 1 billion nanoseconds in a second and we need to handle double that
00068 // because of the implementations of addition etc that we use.
00069 //
00070 // The maximum valid RealTime on a 32-bit system is somewhere around
00071 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
00072 
00073 #define ONE_BILLION 1000000000
00074 
00075 RealTime::RealTime(int s, int n) :
00076     sec(s), nsec(n)
00077 {
00078     if (sec == 0) {
00079         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
00080         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
00081     } else if (sec < 0) {
00082         while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
00083         while (nsec > 0)             { nsec -= ONE_BILLION; ++sec; }
00084     } else { 
00085         while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
00086         while (nsec < 0)             { nsec += ONE_BILLION; --sec; }
00087     }
00088 }
00089 
00090 RealTime
00091 RealTime::fromSeconds(double sec)
00092 {
00093     return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
00094 }
00095 
00096 RealTime
00097 RealTime::fromMilliseconds(int msec)
00098 {
00099     return RealTime(msec / 1000, (msec % 1000) * 1000000);
00100 }
00101 
00102 #ifndef _WIN32
00103 RealTime
00104 RealTime::fromTimeval(const struct timeval &tv)
00105 {
00106     return RealTime(tv.tv_sec, tv.tv_usec * 1000);
00107 }
00108 #endif
00109 
00110 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
00111 {
00112     if (rt < RealTime::zeroTime) {
00113         out << "-";
00114     } else {
00115         out << " ";
00116     }
00117 
00118     int s = (rt.sec < 0 ? -rt.sec : rt.sec);
00119     int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
00120 
00121     out << s << ".";
00122 
00123     int nn(n);
00124     if (nn == 0) out << "00000000";
00125     else while (nn < (ONE_BILLION / 10)) {
00126         out << "0";
00127         nn *= 10;
00128     }
00129     
00130     out << n << "R";
00131     return out;
00132 }
00133 
00134 std::string
00135 RealTime::toString() const
00136 {
00137     std::stringstream out;
00138     out << *this;
00139     
00140 #if (__GNUC__ < 3)
00141     out << std::ends;
00142 #endif
00143 
00144     std::string s = out.str();
00145 
00146     // remove trailing R
00147     return s.substr(0, s.length() - 1);
00148 }
00149 
00150 std::string
00151 RealTime::toText(bool fixedDp) const
00152 {
00153     if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
00154 
00155     std::stringstream out;
00156 
00157     if (sec >= 3600) {
00158         out << (sec / 3600) << ":";
00159     }
00160 
00161     if (sec >= 60) {
00162         out << (sec % 3600) / 60 << ":";
00163     }
00164 
00165     if (sec >= 10) {
00166         out << ((sec % 60) / 10);
00167     }
00168 
00169     out << (sec % 10);
00170     
00171     int ms = msec();
00172 
00173     if (ms != 0) {
00174         out << ".";
00175         out << (ms / 100);
00176         ms = ms % 100;
00177         if (ms != 0) {
00178             out << (ms / 10);
00179             ms = ms % 10;
00180         } else if (fixedDp) {
00181             out << "0";
00182         }
00183         if (ms != 0) {
00184             out << ms;
00185         } else if (fixedDp) {
00186             out << "0";
00187         }
00188     } else if (fixedDp) {
00189         out << ".000";
00190     }
00191         
00192 #if (__GNUC__ < 3)
00193     out << std::ends;
00194 #endif
00195 
00196     std::string s = out.str();
00197 
00198     return s;
00199 }
00200 
00201 
00202 RealTime
00203 RealTime::operator/(int d) const
00204 {
00205     int secdiv = sec / d;
00206     int secrem = sec % d;
00207 
00208     double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
00209     
00210     return RealTime(secdiv, int(nsecdiv + 0.5));
00211 }
00212 
00213 double 
00214 RealTime::operator/(const RealTime &r) const
00215 {
00216     double lTotal = double(sec) * ONE_BILLION + double(nsec);
00217     double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
00218     
00219     if (rTotal == 0) return 0.0;
00220     else return lTotal/rTotal;
00221 }
00222 
00223 long
00224 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
00225 {
00226     if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
00227 
00228     // We like integers.  The last term is always zero unless the
00229     // sample rate is greater than 1MHz, but hell, you never know...
00230 
00231     long frame =
00232         time.sec * sampleRate +
00233         (time.msec() * sampleRate) / 1000 +
00234         ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
00235         ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
00236 
00237     return frame;
00238 }
00239 
00240 RealTime
00241 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
00242 {
00243     if (frame < 0) return -frame2RealTime(-frame, sampleRate);
00244 
00245     RealTime rt;
00246     rt.sec = frame / long(sampleRate);
00247     frame -= rt.sec * long(sampleRate);
00248     rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
00249     return rt;
00250 }
00251 
00252 const RealTime RealTime::zeroTime(0,0);
00253 
00254 }

Generated on Wed Jun 18 00:10:27 2008 for VampPluginSDK by  doxygen 1.5.6