annotate base/RealTime.cpp @ 6:44bbf5793d84

* Rework handling of layer properties in file I/O -- we now get the individual layers to load and save them rather than doing it via generic property lists in the base class, so as to ensure we read and write meaningful values rather than generic int values requiring conversion.
author Chris Cannam
date Thu, 19 Jan 2006 12:54:38 +0000
parents d86891498eef
children 2fb933f88604
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@2 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 /*
Chris@0 11 This is a modified version of a source file from the
Chris@0 12 Rosegarden MIDI and audio sequencer and notation editor.
Chris@0 13 This file copyright 2000-2005 Chris Cannam.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include <iostream>
Chris@0 17
Chris@0 18 #if (__GNUC__ < 3)
Chris@0 19 #include <strstream>
Chris@0 20 #define stringstream strstream
Chris@0 21 #else
Chris@0 22 #include <sstream>
Chris@0 23 #endif
Chris@0 24
Chris@0 25 using std::cerr;
Chris@0 26 using std::endl;
Chris@0 27
Chris@0 28 #include "base/RealTime.h"
Chris@0 29
Chris@0 30 // A RealTime consists of two ints that must be at least 32 bits each.
Chris@0 31 // A signed 32-bit int can store values exceeding +/- 2 billion. This
Chris@0 32 // means we can safely use our lower int for nanoseconds, as there are
Chris@0 33 // 1 billion nanoseconds in a second and we need to handle double that
Chris@0 34 // because of the implementations of addition etc that we use.
Chris@0 35 //
Chris@0 36 // The maximum valid RealTime on a 32-bit system is somewhere around
Chris@0 37 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
Chris@0 38
Chris@0 39 #define ONE_BILLION 1000000000
Chris@0 40
Chris@0 41 RealTime::RealTime(int s, int n) :
Chris@0 42 sec(s), nsec(n)
Chris@0 43 {
Chris@0 44 if (sec == 0) {
Chris@0 45 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
Chris@0 46 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
Chris@0 47 } else if (sec < 0) {
Chris@0 48 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
Chris@0 49 while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
Chris@0 50 } else {
Chris@0 51 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
Chris@0 52 while (nsec < 0) { nsec += ONE_BILLION; --sec; }
Chris@0 53 }
Chris@0 54 }
Chris@0 55
Chris@0 56
Chris@0 57 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
Chris@0 58 {
Chris@0 59 if (rt < RealTime::zeroTime) {
Chris@0 60 out << "-";
Chris@0 61 } else {
Chris@0 62 out << " ";
Chris@0 63 }
Chris@0 64
Chris@0 65 int s = (rt.sec < 0 ? -rt.sec : rt.sec);
Chris@0 66 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
Chris@0 67
Chris@0 68 out << s << ".";
Chris@0 69
Chris@0 70 int nn(n);
Chris@0 71 if (nn == 0) out << "00000000";
Chris@0 72 else while (nn < (ONE_BILLION / 10)) {
Chris@0 73 out << "0";
Chris@0 74 nn *= 10;
Chris@0 75 }
Chris@0 76
Chris@0 77 out << n << "R";
Chris@0 78 return out;
Chris@0 79 }
Chris@0 80
Chris@0 81 std::string
Chris@0 82 RealTime::toString() const
Chris@0 83 {
Chris@0 84 std::stringstream out;
Chris@0 85 out << *this;
Chris@0 86
Chris@0 87 #if (__GNUC__ < 3)
Chris@0 88 out << std::ends;
Chris@0 89 #endif
Chris@0 90
Chris@0 91 std::string s = out.str();
Chris@0 92
Chris@0 93 // remove trailing R
Chris@0 94 return s.substr(0, s.length() - 1);
Chris@0 95 }
Chris@0 96
Chris@0 97 std::string
Chris@0 98 RealTime::toText(bool fixedDp) const
Chris@0 99 {
Chris@0 100 if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
Chris@0 101
Chris@0 102 std::stringstream out;
Chris@0 103
Chris@0 104 if (sec >= 3600) {
Chris@0 105 out << (sec / 3600) << ":";
Chris@0 106 }
Chris@0 107
Chris@0 108 if (sec >= 60) {
Chris@0 109 out << (sec % 3600) / 60 << ":";
Chris@0 110 }
Chris@0 111
Chris@0 112 if (sec >= 10) {
Chris@0 113 out << ((sec % 60) / 10);
Chris@0 114 }
Chris@0 115
Chris@0 116 out << (sec % 10);
Chris@0 117
Chris@0 118 int ms = msec();
Chris@0 119
Chris@0 120 if (ms != 0) {
Chris@0 121 out << ".";
Chris@0 122 out << (ms / 100);
Chris@0 123 ms = ms % 100;
Chris@0 124 if (ms != 0) {
Chris@0 125 out << (ms / 10);
Chris@0 126 ms = ms % 10;
Chris@0 127 } else if (fixedDp) {
Chris@0 128 out << "0";
Chris@0 129 }
Chris@0 130 if (ms != 0) {
Chris@0 131 out << ms;
Chris@0 132 } else if (fixedDp) {
Chris@0 133 out << "0";
Chris@0 134 }
Chris@0 135 } else if (fixedDp) {
Chris@0 136 out << ".000";
Chris@0 137 }
Chris@0 138
Chris@0 139 #if (__GNUC__ < 3)
Chris@0 140 out << std::ends;
Chris@0 141 #endif
Chris@0 142
Chris@0 143 std::string s = out.str();
Chris@0 144
Chris@0 145 return s;
Chris@0 146 }
Chris@0 147
Chris@0 148
Chris@0 149 RealTime
Chris@0 150 RealTime::operator/(int d) const
Chris@0 151 {
Chris@0 152 int secdiv = sec / d;
Chris@0 153 int secrem = sec % d;
Chris@0 154
Chris@0 155 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
Chris@0 156
Chris@0 157 return RealTime(secdiv, int(nsecdiv + 0.5));
Chris@0 158 }
Chris@0 159
Chris@0 160 double
Chris@0 161 RealTime::operator/(const RealTime &r) const
Chris@0 162 {
Chris@0 163 double lTotal = double(sec) * ONE_BILLION + double(nsec);
Chris@0 164 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
Chris@0 165
Chris@0 166 if (rTotal == 0) return 0.0;
Chris@0 167 else return lTotal/rTotal;
Chris@0 168 }
Chris@0 169
Chris@0 170 long
Chris@0 171 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
Chris@0 172 {
Chris@0 173 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
Chris@0 174
Chris@0 175 // We like integers. The last term is always zero unless the
Chris@0 176 // sample rate is greater than 1MHz, but hell, you never know...
Chris@0 177
Chris@0 178 long frame =
Chris@0 179 time.sec * sampleRate +
Chris@0 180 (time.msec() * sampleRate) / 1000 +
Chris@0 181 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
Chris@0 182 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
Chris@0 183
Chris@0 184 return frame;
Chris@0 185 }
Chris@0 186
Chris@0 187 RealTime
Chris@0 188 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
Chris@0 189 {
Chris@0 190 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
Chris@0 191
Chris@0 192 RealTime rt;
Chris@0 193 rt.sec = frame / long(sampleRate);
Chris@0 194 frame -= rt.sec * long(sampleRate);
Chris@0 195 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
Chris@0 196 return rt;
Chris@0 197 }
Chris@0 198
Chris@0 199 const RealTime RealTime::zeroTime(0,0);
Chris@0 200