RAUL
0.8.0
|
00001 /* This file is part of Raul. 00002 * Copyright (C) 2008-2009 David Robillard <http://drobilla.net> 00003 * 00004 * Raul is free software; you can redistribute it and/or modify it under the 00005 * terms of the GNU General Public License as published by the Free Software 00006 * Foundation; either version 2 of the License, or (at your option) any later 00007 * version. 00008 * 00009 * Raul is distributed in the hope that it will be useful, but WITHOUT ANY 00010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00011 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. 00012 * 00013 * You should have received a copy of the GNU General Public License along 00014 * with this program; if not, write to the Free Software Foundation, Inc., 00015 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00016 */ 00017 00018 #ifndef RAUL_TIME_STAMP_HPP 00019 #define RAUL_TIME_STAMP_HPP 00020 00021 #include <limits> 00022 #include <stdint.h> 00023 #include <math.h> 00024 #include <cassert> 00025 #include <iostream> 00026 00027 namespace Raul { 00028 00029 00033 class TimeUnit { 00034 public: 00035 enum Type { 00036 FRAMES, 00037 BEATS, 00038 SECONDS 00039 }; 00040 00044 inline TimeUnit(Type type, uint32_t ppt) { 00045 assert(type == SECONDS || ppt != 0); 00046 _type = type; 00047 _ppt = ppt; 00048 } 00049 00050 static inline TimeUnit frames(uint32_t srate) { return TimeUnit(FRAMES, srate); } 00051 static inline TimeUnit beats(uint32_t ppqn) { return TimeUnit(BEATS, ppqn); } 00052 static inline TimeUnit seconds() { return TimeUnit(BEATS, std::numeric_limits<uint32_t>::max()); } 00053 00054 inline Type type() const { return _type; } 00055 inline uint32_t ppt() const { return _ppt; } 00056 00057 inline bool operator==(const TimeUnit& rhs) const { 00058 return (_type == rhs._type && _ppt == rhs._ppt); 00059 } 00060 00061 inline bool operator!=(const TimeUnit& rhs) const { 00062 return (_type != rhs._type || _ppt != rhs._ppt); 00063 } 00064 00065 private: 00066 Type _type; 00067 uint32_t _ppt; 00068 }; 00069 00070 00080 class TimeStamp { 00081 public: 00082 inline TimeStamp(TimeUnit unit, uint32_t ticks=0, uint32_t subticks=0) 00083 : _ticks(ticks) 00084 , _subticks(subticks) 00085 , _unit(unit) 00086 {} 00087 00088 inline TimeStamp(TimeUnit unit, double dec) 00089 : _ticks(static_cast<uint32_t>(floor(dec))) 00090 , _subticks((dec - floor(dec)) * unit.ppt()) 00091 , _unit(unit) 00092 { 00093 assert(dec >= 0); 00094 assert(dec <= std::numeric_limits<uint32_t>::max()); 00095 } 00096 00097 inline TimeUnit unit() const { return _unit; } 00098 inline uint32_t ticks() const { return _ticks; } 00099 inline uint32_t subticks() const { return _subticks; } 00100 00101 inline double to_double() const { 00102 return _ticks + (_subticks / static_cast<double>(_unit.ppt())); 00103 } 00104 00105 inline bool is_zero() const { 00106 return _ticks == 0 && _subticks == 0; 00107 } 00108 00109 inline TimeStamp& operator=(const TimeStamp& rhs) { 00110 _ticks = rhs._ticks; 00111 _subticks = rhs._subticks; 00112 _unit = rhs._unit; 00113 return *this; 00114 } 00115 00116 inline TimeStamp& operator=(uint32_t ticks) { 00117 _ticks = ticks; 00118 _subticks = 0; 00119 return *this; 00120 } 00121 00122 inline bool operator==(const TimeStamp& rhs) const { 00123 return _ticks == rhs._ticks 00124 && _subticks == rhs._subticks 00125 && _unit == rhs._unit; 00126 } 00127 00128 inline bool operator!=(const TimeStamp& rhs) const { 00129 return ! operator==(rhs); 00130 } 00131 00132 inline bool operator<(const TimeStamp& rhs) const { 00133 assert(_unit == rhs._unit); 00134 return (_ticks < rhs._ticks 00135 || (_ticks == rhs._ticks && _subticks < rhs._subticks)); 00136 } 00137 00138 inline bool operator>(const TimeStamp& rhs) const { 00139 assert(_unit == rhs._unit); 00140 return (_ticks > rhs._ticks 00141 || (_ticks == rhs._ticks && _subticks > rhs._subticks)); 00142 } 00143 00144 inline bool operator<=(const TimeStamp& rhs) const { 00145 return (*this == rhs) || ((*this) < rhs); 00146 } 00147 00148 inline bool operator>=(const TimeStamp& rhs) const { 00149 return (*this == rhs) || ((*this) > rhs); 00150 } 00151 00152 inline TimeStamp& operator+=(const TimeStamp& rhs) { 00153 assert(_unit == rhs._unit); 00154 _ticks += rhs._ticks; 00155 if (_subticks + rhs._subticks <= _unit.ppt()) { 00156 _subticks += rhs._subticks; 00157 } else if (rhs._subticks > 0) { 00158 ++_ticks; 00159 _subticks = rhs._subticks + _subticks - _unit.ppt(); 00160 } 00161 return *this; 00162 } 00163 00164 inline TimeStamp& operator-=(const TimeStamp& rhs) { 00165 assert(_unit == rhs._unit); 00166 assert(rhs <= *this); 00167 _ticks -= rhs._ticks; 00168 if (_subticks >= rhs._subticks) { 00169 _subticks -= rhs._subticks; 00170 } else if (rhs._subticks > 0) { 00171 --_ticks; 00172 _subticks = _unit.ppt() - (rhs._subticks - _subticks); 00173 } 00174 return *this; 00175 } 00176 00177 inline TimeStamp operator+(const TimeStamp& rhs) const { 00178 assert(_unit == rhs._unit); 00179 TimeStamp result = *this; 00180 result += rhs; 00181 return result; 00182 } 00183 00184 inline TimeStamp operator-(const TimeStamp& rhs) const { 00185 assert(_unit == rhs._unit); 00186 TimeStamp result = *this; 00187 result -= rhs; 00188 return result; 00189 } 00190 00191 private: 00192 uint32_t _ticks; 00193 uint32_t _subticks; 00194 TimeUnit _unit; 00195 }; 00196 00197 00198 static inline std::ostream& 00199 operator<<(std::ostream& os, const TimeStamp& t) 00200 { 00201 os << t.ticks() << ":" << t.subticks(); 00202 switch (t.unit().type()) { 00203 case TimeUnit::FRAMES: 00204 os << " frames"; 00205 break; 00206 case TimeUnit::BEATS: 00207 os << " beats"; 00208 break; 00209 case TimeUnit::SECONDS: 00210 os << " seconds"; 00211 break; 00212 } 00213 return os; 00214 } 00215 00216 00217 class FrameStamp : public TimeStamp { 00218 public: 00219 inline FrameStamp(uint32_t rate, uint32_t ticks=0, uint32_t subticks=0) 00220 : TimeStamp(TimeUnit(TimeUnit::FRAMES, rate), ticks, subticks) 00221 {} 00222 }; 00223 00224 00225 class BeatStamp : public TimeStamp { 00226 public: 00227 inline BeatStamp(uint32_t ppqn, uint32_t ticks=0, uint32_t subticks=0) 00228 : TimeStamp(TimeUnit(TimeUnit::BEATS, ppqn), ticks, subticks) 00229 {} 00230 }; 00231 00232 00235 typedef TimeStamp TimeDuration; 00236 00237 00238 } // namespace Raul 00239 00240 #endif // RAUL_TIME_STAMP_HPP