00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 }
00239
00240 #endif // RAUL_TIME_STAMP_HPP