annotate base/RealTime.cpp @ 33:51e158b505da

* Rearrange spectrogram cacheing so that gain, normalization, instantaneous frequency calculations etc can be done from the cached data (increasing the size of the cache, but also the usability).
author Chris Cannam
date Thu, 23 Feb 2006 18:01:31 +0000
parents 090c22aa726a
children 39ae3dee27b9
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@17 13 This file copyright 2000-2006 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@26 29 #include "sys/time.h"
Chris@0 30
Chris@0 31 // A RealTime consists of two ints that must be at least 32 bits each.
Chris@0 32 // A signed 32-bit int can store values exceeding +/- 2 billion. This
Chris@0 33 // means we can safely use our lower int for nanoseconds, as there are
Chris@0 34 // 1 billion nanoseconds in a second and we need to handle double that
Chris@0 35 // because of the implementations of addition etc that we use.
Chris@0 36 //
Chris@0 37 // The maximum valid RealTime on a 32-bit system is somewhere around
Chris@0 38 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
Chris@0 39
Chris@0 40 #define ONE_BILLION 1000000000
Chris@0 41
Chris@0 42 RealTime::RealTime(int s, int n) :
Chris@0 43 sec(s), nsec(n)
Chris@0 44 {
Chris@0 45 if (sec == 0) {
Chris@0 46 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
Chris@0 47 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
Chris@0 48 } else if (sec < 0) {
Chris@0 49 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
Chris@0 50 while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
Chris@0 51 } else {
Chris@0 52 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
Chris@0 53 while (nsec < 0) { nsec += ONE_BILLION; --sec; }
Chris@0 54 }
Chris@0 55 }
Chris@0 56
Chris@26 57 RealTime
Chris@26 58 RealTime::fromSeconds(double sec)
Chris@26 59 {
Chris@26 60 return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION));
Chris@26 61 }
Chris@26 62
Chris@26 63 RealTime
Chris@26 64 RealTime::fromMilliseconds(int msec)
Chris@26 65 {
Chris@26 66 return RealTime(msec / 1000, (msec % 1000) * 1000000);
Chris@26 67 }
Chris@26 68
Chris@26 69 RealTime
Chris@26 70 RealTime::fromTimeval(const struct timeval &tv)
Chris@26 71 {
Chris@26 72 return RealTime(tv.tv_sec, tv.tv_usec * 1000);
Chris@26 73 }
Chris@0 74
Chris@0 75 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
Chris@0 76 {
Chris@0 77 if (rt < RealTime::zeroTime) {
Chris@0 78 out << "-";
Chris@0 79 } else {
Chris@0 80 out << " ";
Chris@0 81 }
Chris@0 82
Chris@0 83 int s = (rt.sec < 0 ? -rt.sec : rt.sec);
Chris@0 84 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
Chris@0 85
Chris@0 86 out << s << ".";
Chris@0 87
Chris@0 88 int nn(n);
Chris@0 89 if (nn == 0) out << "00000000";
Chris@0 90 else while (nn < (ONE_BILLION / 10)) {
Chris@0 91 out << "0";
Chris@0 92 nn *= 10;
Chris@0 93 }
Chris@0 94
Chris@0 95 out << n << "R";
Chris@0 96 return out;
Chris@0 97 }
Chris@0 98
Chris@0 99 std::string
Chris@0 100 RealTime::toString() const
Chris@0 101 {
Chris@0 102 std::stringstream out;
Chris@0 103 out << *this;
Chris@0 104
Chris@0 105 #if (__GNUC__ < 3)
Chris@0 106 out << std::ends;
Chris@0 107 #endif
Chris@0 108
Chris@0 109 std::string s = out.str();
Chris@0 110
Chris@0 111 // remove trailing R
Chris@0 112 return s.substr(0, s.length() - 1);
Chris@0 113 }
Chris@0 114
Chris@0 115 std::string
Chris@0 116 RealTime::toText(bool fixedDp) const
Chris@0 117 {
Chris@0 118 if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
Chris@0 119
Chris@0 120 std::stringstream out;
Chris@0 121
Chris@0 122 if (sec >= 3600) {
Chris@0 123 out << (sec / 3600) << ":";
Chris@0 124 }
Chris@0 125
Chris@0 126 if (sec >= 60) {
Chris@0 127 out << (sec % 3600) / 60 << ":";
Chris@0 128 }
Chris@0 129
Chris@0 130 if (sec >= 10) {
Chris@0 131 out << ((sec % 60) / 10);
Chris@0 132 }
Chris@0 133
Chris@0 134 out << (sec % 10);
Chris@0 135
Chris@0 136 int ms = msec();
Chris@0 137
Chris@0 138 if (ms != 0) {
Chris@0 139 out << ".";
Chris@0 140 out << (ms / 100);
Chris@0 141 ms = ms % 100;
Chris@0 142 if (ms != 0) {
Chris@0 143 out << (ms / 10);
Chris@0 144 ms = ms % 10;
Chris@0 145 } else if (fixedDp) {
Chris@0 146 out << "0";
Chris@0 147 }
Chris@0 148 if (ms != 0) {
Chris@0 149 out << ms;
Chris@0 150 } else if (fixedDp) {
Chris@0 151 out << "0";
Chris@0 152 }
Chris@0 153 } else if (fixedDp) {
Chris@0 154 out << ".000";
Chris@0 155 }
Chris@0 156
Chris@0 157 #if (__GNUC__ < 3)
Chris@0 158 out << std::ends;
Chris@0 159 #endif
Chris@0 160
Chris@0 161 std::string s = out.str();
Chris@0 162
Chris@0 163 return s;
Chris@0 164 }
Chris@0 165
Chris@0 166
Chris@0 167 RealTime
Chris@0 168 RealTime::operator/(int d) const
Chris@0 169 {
Chris@0 170 int secdiv = sec / d;
Chris@0 171 int secrem = sec % d;
Chris@0 172
Chris@0 173 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
Chris@0 174
Chris@0 175 return RealTime(secdiv, int(nsecdiv + 0.5));
Chris@0 176 }
Chris@0 177
Chris@0 178 double
Chris@0 179 RealTime::operator/(const RealTime &r) const
Chris@0 180 {
Chris@0 181 double lTotal = double(sec) * ONE_BILLION + double(nsec);
Chris@0 182 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
Chris@0 183
Chris@0 184 if (rTotal == 0) return 0.0;
Chris@0 185 else return lTotal/rTotal;
Chris@0 186 }
Chris@0 187
Chris@0 188 long
Chris@0 189 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
Chris@0 190 {
Chris@0 191 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
Chris@0 192
Chris@0 193 // We like integers. The last term is always zero unless the
Chris@0 194 // sample rate is greater than 1MHz, but hell, you never know...
Chris@0 195
Chris@0 196 long frame =
Chris@0 197 time.sec * sampleRate +
Chris@0 198 (time.msec() * sampleRate) / 1000 +
Chris@0 199 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
Chris@0 200 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
Chris@0 201
Chris@0 202 return frame;
Chris@0 203 }
Chris@0 204
Chris@0 205 RealTime
Chris@0 206 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
Chris@0 207 {
Chris@0 208 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
Chris@0 209
Chris@0 210 RealTime rt;
Chris@0 211 rt.sec = frame / long(sampleRate);
Chris@0 212 frame -= rt.sec * long(sampleRate);
Chris@0 213 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
Chris@0 214 return rt;
Chris@0 215 }
Chris@0 216
Chris@0 217 const RealTime RealTime::zeroTime(0,0);
Chris@0 218