cannam@3: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@3: cannam@3: /* cannam@3: Vamp cannam@3: cannam@3: An API for audio analysis and feature extraction plugins. cannam@3: cannam@3: Centre for Digital Music, Queen Mary, University of London. cannam@3: Copyright 2006 Chris Cannam. cannam@3: cannam@3: Permission is hereby granted, free of charge, to any person cannam@3: obtaining a copy of this software and associated documentation cannam@3: files (the "Software"), to deal in the Software without cannam@3: restriction, including without limitation the rights to use, copy, cannam@3: modify, merge, publish, distribute, sublicense, and/or sell copies cannam@3: of the Software, and to permit persons to whom the Software is cannam@3: furnished to do so, subject to the following conditions: cannam@3: cannam@3: The above copyright notice and this permission notice shall be cannam@3: included in all copies or substantial portions of the Software. cannam@3: cannam@3: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@3: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@3: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND cannam@6: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR cannam@3: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@3: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@3: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@3: cannam@3: Except as contained in this notice, the names of the Centre for cannam@3: Digital Music; Queen Mary, University of London; and Chris Cannam cannam@3: shall not be used in advertising or otherwise to promote the sale, cannam@3: use or other dealings in this Software without prior written cannam@3: authorization. cannam@3: */ cannam@3: cannam@3: /* cannam@3: This is a modified version of a source file from the cannam@3: Rosegarden MIDI and audio sequencer and notation editor. cannam@10: This file copyright 2000-2006 Chris Cannam. cannam@10: Relicensed by the author as detailed above. cannam@3: */ cannam@3: cannam@3: #include cannam@3: cannam@3: #if (__GNUC__ < 3) cannam@3: #include cannam@3: #define stringstream strstream cannam@3: #else cannam@3: #include cannam@3: #endif cannam@3: cannam@3: using std::cerr; cannam@3: using std::endl; cannam@3: cannam@3: #include "RealTime.h" cannam@3: #include "sys/time.h" cannam@3: cannam@3: namespace Vamp { cannam@3: cannam@3: // A RealTime consists of two ints that must be at least 32 bits each. cannam@3: // A signed 32-bit int can store values exceeding +/- 2 billion. This cannam@3: // means we can safely use our lower int for nanoseconds, as there are cannam@3: // 1 billion nanoseconds in a second and we need to handle double that cannam@3: // because of the implementations of addition etc that we use. cannam@3: // cannam@3: // The maximum valid RealTime on a 32-bit system is somewhere around cannam@3: // 68 years: 999999999 nanoseconds longer than the classic Unix epoch. cannam@3: cannam@3: #define ONE_BILLION 1000000000 cannam@3: cannam@3: RealTime::RealTime(int s, int n) : cannam@3: sec(s), nsec(n) cannam@3: { cannam@3: if (sec == 0) { cannam@3: while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } cannam@3: while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } cannam@3: } else if (sec < 0) { cannam@3: while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } cannam@3: while (nsec > 0) { nsec -= ONE_BILLION; ++sec; } cannam@3: } else { cannam@3: while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } cannam@3: while (nsec < 0) { nsec += ONE_BILLION; --sec; } cannam@3: } cannam@3: } cannam@3: cannam@3: RealTime cannam@3: RealTime::fromSeconds(double sec) cannam@3: { cannam@3: return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION)); cannam@3: } cannam@3: cannam@3: RealTime cannam@3: RealTime::fromMilliseconds(int msec) cannam@3: { cannam@3: return RealTime(msec / 1000, (msec % 1000) * 1000000); cannam@3: } cannam@3: cannam@3: RealTime cannam@3: RealTime::fromTimeval(const struct timeval &tv) cannam@3: { cannam@3: return RealTime(tv.tv_sec, tv.tv_usec * 1000); cannam@3: } cannam@3: cannam@3: std::ostream &operator<<(std::ostream &out, const RealTime &rt) cannam@3: { cannam@3: if (rt < RealTime::zeroTime) { cannam@3: out << "-"; cannam@3: } else { cannam@3: out << " "; cannam@3: } cannam@3: cannam@3: int s = (rt.sec < 0 ? -rt.sec : rt.sec); cannam@3: int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec); cannam@3: cannam@3: out << s << "."; cannam@3: cannam@3: int nn(n); cannam@3: if (nn == 0) out << "00000000"; cannam@3: else while (nn < (ONE_BILLION / 10)) { cannam@3: out << "0"; cannam@3: nn *= 10; cannam@3: } cannam@3: cannam@3: out << n << "R"; cannam@3: return out; cannam@3: } cannam@3: cannam@3: std::string cannam@3: RealTime::toString() const cannam@3: { cannam@3: std::stringstream out; cannam@3: out << *this; cannam@3: cannam@3: #if (__GNUC__ < 3) cannam@3: out << std::ends; cannam@3: #endif cannam@3: cannam@3: std::string s = out.str(); cannam@3: cannam@3: // remove trailing R cannam@3: return s.substr(0, s.length() - 1); cannam@3: } cannam@3: cannam@3: std::string cannam@3: RealTime::toText(bool fixedDp) const cannam@3: { cannam@3: if (*this < RealTime::zeroTime) return "-" + (-*this).toText(); cannam@3: cannam@3: std::stringstream out; cannam@3: cannam@3: if (sec >= 3600) { cannam@3: out << (sec / 3600) << ":"; cannam@3: } cannam@3: cannam@3: if (sec >= 60) { cannam@3: out << (sec % 3600) / 60 << ":"; cannam@3: } cannam@3: cannam@3: if (sec >= 10) { cannam@3: out << ((sec % 60) / 10); cannam@3: } cannam@3: cannam@3: out << (sec % 10); cannam@3: cannam@3: int ms = msec(); cannam@3: cannam@3: if (ms != 0) { cannam@3: out << "."; cannam@3: out << (ms / 100); cannam@3: ms = ms % 100; cannam@3: if (ms != 0) { cannam@3: out << (ms / 10); cannam@3: ms = ms % 10; cannam@3: } else if (fixedDp) { cannam@3: out << "0"; cannam@3: } cannam@3: if (ms != 0) { cannam@3: out << ms; cannam@3: } else if (fixedDp) { cannam@3: out << "0"; cannam@3: } cannam@3: } else if (fixedDp) { cannam@3: out << ".000"; cannam@3: } cannam@3: cannam@3: #if (__GNUC__ < 3) cannam@3: out << std::ends; cannam@3: #endif cannam@3: cannam@3: std::string s = out.str(); cannam@3: cannam@3: return s; cannam@3: } cannam@3: cannam@3: cannam@3: RealTime cannam@3: RealTime::operator/(int d) const cannam@3: { cannam@3: int secdiv = sec / d; cannam@3: int secrem = sec % d; cannam@3: cannam@3: double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d; cannam@3: cannam@3: return RealTime(secdiv, int(nsecdiv + 0.5)); cannam@3: } cannam@3: cannam@3: double cannam@3: RealTime::operator/(const RealTime &r) const cannam@3: { cannam@3: double lTotal = double(sec) * ONE_BILLION + double(nsec); cannam@3: double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec); cannam@3: cannam@3: if (rTotal == 0) return 0.0; cannam@3: else return lTotal/rTotal; cannam@3: } cannam@3: cannam@3: long cannam@3: RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate) cannam@3: { cannam@3: if (time < zeroTime) return -realTime2Frame(-time, sampleRate); cannam@3: cannam@3: // We like integers. The last term is always zero unless the cannam@3: // sample rate is greater than 1MHz, but hell, you never know... cannam@3: cannam@3: long frame = cannam@3: time.sec * sampleRate + cannam@3: (time.msec() * sampleRate) / 1000 + cannam@3: ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 + cannam@3: ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000; cannam@3: cannam@3: return frame; cannam@3: } cannam@3: cannam@3: RealTime cannam@3: RealTime::frame2RealTime(long frame, unsigned int sampleRate) cannam@3: { cannam@3: if (frame < 0) return -frame2RealTime(-frame, sampleRate); cannam@3: cannam@3: RealTime rt; cannam@3: rt.sec = frame / long(sampleRate); cannam@3: frame -= rt.sec * long(sampleRate); cannam@3: rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000); cannam@3: return rt; cannam@3: } cannam@3: cannam@3: const RealTime RealTime::zeroTime(0,0); cannam@3: cannam@3: }