annotate base/RealTime.cpp @ 117:c30728d5625c sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents d397ea0a79f5
children fda016f64f7c
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@0 33 #include "base/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@26 65 return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION));
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@0 105 RealTime::toString() 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@0 116 // remove trailing R
Chris@0 117 return s.substr(0, s.length() - 1);
Chris@0 118 }
Chris@0 119
Chris@0 120 std::string
Chris@0 121 RealTime::toText(bool fixedDp) const
Chris@0 122 {
Chris@0 123 if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
Chris@0 124
Chris@0 125 std::stringstream out;
Chris@0 126
Chris@0 127 if (sec >= 3600) {
Chris@0 128 out << (sec / 3600) << ":";
Chris@0 129 }
Chris@0 130
Chris@0 131 if (sec >= 60) {
Chris@0 132 out << (sec % 3600) / 60 << ":";
Chris@0 133 }
Chris@0 134
Chris@0 135 if (sec >= 10) {
Chris@0 136 out << ((sec % 60) / 10);
Chris@0 137 }
Chris@0 138
Chris@0 139 out << (sec % 10);
Chris@0 140
Chris@0 141 int ms = msec();
Chris@0 142
Chris@0 143 if (ms != 0) {
Chris@0 144 out << ".";
Chris@0 145 out << (ms / 100);
Chris@0 146 ms = ms % 100;
Chris@0 147 if (ms != 0) {
Chris@0 148 out << (ms / 10);
Chris@0 149 ms = ms % 10;
Chris@0 150 } else if (fixedDp) {
Chris@0 151 out << "0";
Chris@0 152 }
Chris@0 153 if (ms != 0) {
Chris@0 154 out << ms;
Chris@0 155 } else if (fixedDp) {
Chris@0 156 out << "0";
Chris@0 157 }
Chris@0 158 } else if (fixedDp) {
Chris@0 159 out << ".000";
Chris@0 160 }
Chris@0 161
Chris@0 162 #if (__GNUC__ < 3)
Chris@0 163 out << std::ends;
Chris@0 164 #endif
Chris@0 165
Chris@0 166 std::string s = out.str();
Chris@0 167
Chris@0 168 return s;
Chris@0 169 }
Chris@0 170
Chris@0 171
Chris@0 172 RealTime
Chris@0 173 RealTime::operator/(int d) const
Chris@0 174 {
Chris@0 175 int secdiv = sec / d;
Chris@0 176 int secrem = sec % d;
Chris@0 177
Chris@0 178 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
Chris@0 179
Chris@0 180 return RealTime(secdiv, int(nsecdiv + 0.5));
Chris@0 181 }
Chris@0 182
Chris@0 183 double
Chris@0 184 RealTime::operator/(const RealTime &r) const
Chris@0 185 {
Chris@0 186 double lTotal = double(sec) * ONE_BILLION + double(nsec);
Chris@0 187 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
Chris@0 188
Chris@0 189 if (rTotal == 0) return 0.0;
Chris@0 190 else return lTotal/rTotal;
Chris@0 191 }
Chris@0 192
Chris@0 193 long
Chris@0 194 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
Chris@0 195 {
Chris@0 196 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
Chris@0 197
Chris@0 198 // We like integers. The last term is always zero unless the
Chris@0 199 // sample rate is greater than 1MHz, but hell, you never know...
Chris@0 200
Chris@0 201 long frame =
Chris@0 202 time.sec * sampleRate +
Chris@0 203 (time.msec() * sampleRate) / 1000 +
Chris@0 204 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
Chris@0 205 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
Chris@0 206
Chris@0 207 return frame;
Chris@0 208 }
Chris@0 209
Chris@0 210 RealTime
Chris@0 211 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
Chris@0 212 {
Chris@0 213 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
Chris@0 214
Chris@0 215 RealTime rt;
Chris@0 216 rt.sec = frame / long(sampleRate);
Chris@0 217 frame -= rt.sec * long(sampleRate);
Chris@0 218 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
Chris@0 219 return rt;
Chris@0 220 }
Chris@0 221
Chris@0 222 const RealTime RealTime::zeroTime(0,0);
Chris@0 223