Chris@0: /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: A waveform viewer and audio annotation editor. Chris@0: Chris Cannam, Queen Mary University of London, 2005 Chris@0: Chris@0: This is experimental software. Not for distribution. Chris@0: */ Chris@0: Chris@0: /* Chris@0: This is a modified version of a source file from the Chris@0: Rosegarden MIDI and audio sequencer and notation editor. Chris@0: This file copyright 2000-2005 Chris Cannam. Chris@0: */ Chris@0: Chris@0: #include Chris@0: Chris@0: #if (__GNUC__ < 3) Chris@0: #include Chris@0: #define stringstream strstream Chris@0: #else Chris@0: #include Chris@0: #endif Chris@0: Chris@0: using std::cerr; Chris@0: using std::endl; Chris@0: Chris@0: #include "base/RealTime.h" Chris@0: Chris@0: // A RealTime consists of two ints that must be at least 32 bits each. Chris@0: // A signed 32-bit int can store values exceeding +/- 2 billion. This Chris@0: // means we can safely use our lower int for nanoseconds, as there are Chris@0: // 1 billion nanoseconds in a second and we need to handle double that Chris@0: // because of the implementations of addition etc that we use. Chris@0: // Chris@0: // The maximum valid RealTime on a 32-bit system is somewhere around Chris@0: // 68 years: 999999999 nanoseconds longer than the classic Unix epoch. Chris@0: Chris@0: #define ONE_BILLION 1000000000 Chris@0: Chris@0: RealTime::RealTime(int s, int n) : Chris@0: sec(s), nsec(n) Chris@0: { Chris@0: if (sec == 0) { Chris@0: while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } Chris@0: while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } Chris@0: } else if (sec < 0) { Chris@0: while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } Chris@0: while (nsec > 0) { nsec -= ONE_BILLION; ++sec; } Chris@0: } else { Chris@0: while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } Chris@0: while (nsec < 0) { nsec += ONE_BILLION; --sec; } Chris@0: } Chris@0: } Chris@0: Chris@0: Chris@0: std::ostream &operator<<(std::ostream &out, const RealTime &rt) Chris@0: { Chris@0: if (rt < RealTime::zeroTime) { Chris@0: out << "-"; Chris@0: } else { Chris@0: out << " "; Chris@0: } Chris@0: Chris@0: int s = (rt.sec < 0 ? -rt.sec : rt.sec); Chris@0: int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec); Chris@0: Chris@0: out << s << "."; Chris@0: Chris@0: int nn(n); Chris@0: if (nn == 0) out << "00000000"; Chris@0: else while (nn < (ONE_BILLION / 10)) { Chris@0: out << "0"; Chris@0: nn *= 10; Chris@0: } Chris@0: Chris@0: out << n << "R"; Chris@0: return out; Chris@0: } Chris@0: Chris@0: std::string Chris@0: RealTime::toString() const Chris@0: { Chris@0: std::stringstream out; Chris@0: out << *this; Chris@0: Chris@0: #if (__GNUC__ < 3) Chris@0: out << std::ends; Chris@0: #endif Chris@0: Chris@0: std::string s = out.str(); Chris@0: Chris@0: // remove trailing R Chris@0: return s.substr(0, s.length() - 1); Chris@0: } Chris@0: Chris@0: std::string Chris@0: RealTime::toText(bool fixedDp) const Chris@0: { Chris@0: if (*this < RealTime::zeroTime) return "-" + (-*this).toText(); Chris@0: Chris@0: std::stringstream out; Chris@0: Chris@0: if (sec >= 3600) { Chris@0: out << (sec / 3600) << ":"; Chris@0: } Chris@0: Chris@0: if (sec >= 60) { Chris@0: out << (sec % 3600) / 60 << ":"; Chris@0: } Chris@0: Chris@0: if (sec >= 10) { Chris@0: out << ((sec % 60) / 10); Chris@0: } Chris@0: Chris@0: out << (sec % 10); Chris@0: Chris@0: int ms = msec(); Chris@0: Chris@0: if (ms != 0) { Chris@0: out << "."; Chris@0: out << (ms / 100); Chris@0: ms = ms % 100; Chris@0: if (ms != 0) { Chris@0: out << (ms / 10); Chris@0: ms = ms % 10; Chris@0: } else if (fixedDp) { Chris@0: out << "0"; Chris@0: } Chris@0: if (ms != 0) { Chris@0: out << ms; Chris@0: } else if (fixedDp) { Chris@0: out << "0"; Chris@0: } Chris@0: } else if (fixedDp) { Chris@0: out << ".000"; Chris@0: } Chris@0: Chris@0: #if (__GNUC__ < 3) Chris@0: out << std::ends; Chris@0: #endif Chris@0: Chris@0: std::string s = out.str(); Chris@0: Chris@0: return s; Chris@0: } Chris@0: Chris@0: Chris@0: RealTime Chris@0: RealTime::operator/(int d) const Chris@0: { Chris@0: int secdiv = sec / d; Chris@0: int secrem = sec % d; Chris@0: Chris@0: double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d; Chris@0: Chris@0: return RealTime(secdiv, int(nsecdiv + 0.5)); Chris@0: } Chris@0: Chris@0: double Chris@0: RealTime::operator/(const RealTime &r) const Chris@0: { Chris@0: double lTotal = double(sec) * ONE_BILLION + double(nsec); Chris@0: double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec); Chris@0: Chris@0: if (rTotal == 0) return 0.0; Chris@0: else return lTotal/rTotal; Chris@0: } Chris@0: Chris@0: long Chris@0: RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate) Chris@0: { Chris@0: if (time < zeroTime) return -realTime2Frame(-time, sampleRate); Chris@0: Chris@0: // We like integers. The last term is always zero unless the Chris@0: // sample rate is greater than 1MHz, but hell, you never know... Chris@0: Chris@0: long frame = Chris@0: time.sec * sampleRate + Chris@0: (time.msec() * sampleRate) / 1000 + Chris@0: ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 + Chris@0: ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000; Chris@0: Chris@0: return frame; Chris@0: } Chris@0: Chris@0: RealTime Chris@0: RealTime::frame2RealTime(long frame, unsigned int sampleRate) Chris@0: { Chris@0: if (frame < 0) return -frame2RealTime(-frame, sampleRate); Chris@0: Chris@0: RealTime rt; Chris@0: rt.sec = frame / long(sampleRate); Chris@0: frame -= rt.sec * long(sampleRate); Chris@0: rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000); Chris@0: return rt; Chris@0: } Chris@0: Chris@0: const RealTime RealTime::zeroTime(0,0); Chris@0: