annotate base/RealTime.cpp @ 184:5a916fee6d2d

* Handle generator transforms (plugins whose channel count isn't dependent on number of audio inputs, as they have none) * Be less keen to suspend writing FFT data in spectrogram repaint -- only do it if we find we actually need to query the FFT data (i.e. we aren't repainting an area that hasn't been generated at all yet)
author Chris Cannam
date Tue, 10 Oct 2006 19:04:57 +0000
parents 146eb9e35baa
children 21b9b25bff48
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7
Chris@52 8 This program is free software; you can redistribute it and/or
Chris@52 9 modify it under the terms of the GNU General Public License as
Chris@52 10 published by the Free Software Foundation; either version 2 of the
Chris@52 11 License, or (at your option) any later version. See the file
Chris@52 12 COPYING included with this distribution for more information.
Chris@0 13 */
Chris@0 14
Chris@0 15 /*
Chris@0 16 This is a modified version of a source file from the
Chris@0 17 Rosegarden MIDI and audio sequencer and notation editor.
Chris@17 18 This file copyright 2000-2006 Chris Cannam.
Chris@0 19 */
Chris@0 20
Chris@0 21 #include <iostream>
Chris@0 22
Chris@0 23 #if (__GNUC__ < 3)
Chris@0 24 #include <strstream>
Chris@0 25 #define stringstream strstream
Chris@0 26 #else
Chris@0 27 #include <sstream>
Chris@0 28 #endif
Chris@0 29
Chris@0 30 using std::cerr;
Chris@0 31 using std::endl;
Chris@0 32
Chris@150 33 #include "RealTime.h"
Chris@26 34 #include "sys/time.h"
Chris@0 35
Chris@0 36 // A RealTime consists of two ints that must be at least 32 bits each.
Chris@0 37 // A signed 32-bit int can store values exceeding +/- 2 billion. This
Chris@0 38 // means we can safely use our lower int for nanoseconds, as there are
Chris@0 39 // 1 billion nanoseconds in a second and we need to handle double that
Chris@0 40 // because of the implementations of addition etc that we use.
Chris@0 41 //
Chris@0 42 // The maximum valid RealTime on a 32-bit system is somewhere around
Chris@0 43 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
Chris@0 44
Chris@0 45 #define ONE_BILLION 1000000000
Chris@0 46
Chris@0 47 RealTime::RealTime(int s, int n) :
Chris@0 48 sec(s), nsec(n)
Chris@0 49 {
Chris@0 50 if (sec == 0) {
Chris@0 51 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
Chris@0 52 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
Chris@0 53 } else if (sec < 0) {
Chris@0 54 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
Chris@0 55 while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
Chris@0 56 } else {
Chris@0 57 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
Chris@0 58 while (nsec < 0) { nsec += ONE_BILLION; --sec; }
Chris@0 59 }
Chris@0 60 }
Chris@0 61
Chris@26 62 RealTime
Chris@26 63 RealTime::fromSeconds(double sec)
Chris@26 64 {
Chris@119 65 return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
Chris@26 66 }
Chris@26 67
Chris@26 68 RealTime
Chris@26 69 RealTime::fromMilliseconds(int msec)
Chris@26 70 {
Chris@26 71 return RealTime(msec / 1000, (msec % 1000) * 1000000);
Chris@26 72 }
Chris@26 73
Chris@26 74 RealTime
Chris@26 75 RealTime::fromTimeval(const struct timeval &tv)
Chris@26 76 {
Chris@26 77 return RealTime(tv.tv_sec, tv.tv_usec * 1000);
Chris@26 78 }
Chris@0 79
Chris@0 80 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
Chris@0 81 {
Chris@0 82 if (rt < RealTime::zeroTime) {
Chris@0 83 out << "-";
Chris@0 84 } else {
Chris@0 85 out << " ";
Chris@0 86 }
Chris@0 87
Chris@0 88 int s = (rt.sec < 0 ? -rt.sec : rt.sec);
Chris@0 89 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
Chris@0 90
Chris@0 91 out << s << ".";
Chris@0 92
Chris@0 93 int nn(n);
Chris@0 94 if (nn == 0) out << "00000000";
Chris@0 95 else while (nn < (ONE_BILLION / 10)) {
Chris@0 96 out << "0";
Chris@0 97 nn *= 10;
Chris@0 98 }
Chris@0 99
Chris@0 100 out << n << "R";
Chris@0 101 return out;
Chris@0 102 }
Chris@0 103
Chris@0 104 std::string
Chris@121 105 RealTime::toString(bool align) const
Chris@0 106 {
Chris@0 107 std::stringstream out;
Chris@0 108 out << *this;
Chris@0 109
Chris@0 110 #if (__GNUC__ < 3)
Chris@0 111 out << std::ends;
Chris@0 112 #endif
Chris@0 113
Chris@0 114 std::string s = out.str();
Chris@0 115
Chris@121 116 if (!align && *this >= RealTime::zeroTime) {
Chris@121 117 // remove leading " "
Chris@121 118 s = s.substr(1, s.length() - 1);
Chris@121 119 }
Chris@121 120
Chris@0 121 // remove trailing R
Chris@0 122 return s.substr(0, s.length() - 1);
Chris@0 123 }
Chris@0 124
Chris@0 125 std::string
Chris@0 126 RealTime::toText(bool fixedDp) const
Chris@0 127 {
Chris@0 128 if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
Chris@0 129
Chris@0 130 std::stringstream out;
Chris@0 131
Chris@0 132 if (sec >= 3600) {
Chris@0 133 out << (sec / 3600) << ":";
Chris@0 134 }
Chris@0 135
Chris@0 136 if (sec >= 60) {
Chris@0 137 out << (sec % 3600) / 60 << ":";
Chris@0 138 }
Chris@0 139
Chris@0 140 if (sec >= 10) {
Chris@0 141 out << ((sec % 60) / 10);
Chris@0 142 }
Chris@0 143
Chris@0 144 out << (sec % 10);
Chris@0 145
Chris@0 146 int ms = msec();
Chris@0 147
Chris@0 148 if (ms != 0) {
Chris@0 149 out << ".";
Chris@0 150 out << (ms / 100);
Chris@0 151 ms = ms % 100;
Chris@0 152 if (ms != 0) {
Chris@0 153 out << (ms / 10);
Chris@0 154 ms = ms % 10;
Chris@0 155 } else if (fixedDp) {
Chris@0 156 out << "0";
Chris@0 157 }
Chris@0 158 if (ms != 0) {
Chris@0 159 out << ms;
Chris@0 160 } else if (fixedDp) {
Chris@0 161 out << "0";
Chris@0 162 }
Chris@0 163 } else if (fixedDp) {
Chris@0 164 out << ".000";
Chris@0 165 }
Chris@0 166
Chris@0 167 #if (__GNUC__ < 3)
Chris@0 168 out << std::ends;
Chris@0 169 #endif
Chris@0 170
Chris@0 171 std::string s = out.str();
Chris@0 172
Chris@0 173 return s;
Chris@0 174 }
Chris@0 175
Chris@183 176 RealTime
Chris@183 177 RealTime::operator*(int m) const
Chris@183 178 {
Chris@183 179 double t = (double(nsec) / ONE_BILLION) * m;
Chris@183 180 t += sec * m;
Chris@183 181 return fromSeconds(t);
Chris@183 182 }
Chris@0 183
Chris@0 184 RealTime
Chris@0 185 RealTime::operator/(int d) const
Chris@0 186 {
Chris@0 187 int secdiv = sec / d;
Chris@0 188 int secrem = sec % d;
Chris@0 189
Chris@0 190 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
Chris@0 191
Chris@0 192 return RealTime(secdiv, int(nsecdiv + 0.5));
Chris@0 193 }
Chris@0 194
Chris@0 195 double
Chris@0 196 RealTime::operator/(const RealTime &r) const
Chris@0 197 {
Chris@0 198 double lTotal = double(sec) * ONE_BILLION + double(nsec);
Chris@0 199 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
Chris@0 200
Chris@0 201 if (rTotal == 0) return 0.0;
Chris@0 202 else return lTotal/rTotal;
Chris@0 203 }
Chris@0 204
Chris@0 205 long
Chris@0 206 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
Chris@0 207 {
Chris@0 208 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
Chris@0 209
Chris@0 210 // We like integers. The last term is always zero unless the
Chris@0 211 // sample rate is greater than 1MHz, but hell, you never know...
Chris@0 212
Chris@0 213 long frame =
Chris@0 214 time.sec * sampleRate +
Chris@0 215 (time.msec() * sampleRate) / 1000 +
Chris@0 216 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
Chris@0 217 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
Chris@0 218
Chris@0 219 return frame;
Chris@0 220 }
Chris@0 221
Chris@0 222 RealTime
Chris@0 223 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
Chris@0 224 {
Chris@0 225 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
Chris@0 226
Chris@0 227 RealTime rt;
Chris@0 228 rt.sec = frame / long(sampleRate);
Chris@0 229 frame -= rt.sec * long(sampleRate);
Chris@0 230 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
Chris@0 231 return rt;
Chris@0 232 }
Chris@0 233
Chris@0 234 const RealTime RealTime::zeroTime(0,0);
Chris@0 235