TimeStamp.hpp
/* This file is part of Raul.
* Copyright (C) 2008-2009 David Robillard <http://drobilla.net>
*
* Raul is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* Raul is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RAUL_TIME_STAMP_HPP
#define RAUL_TIME_STAMP_HPP
#include <limits>
#include <stdint.h>
#include <math.h>
#include <cassert>
#include <iostream>
namespace Raul {
class TimeUnit {
public:
enum Type {
FRAMES,
BEATS,
SECONDS
};
inline TimeUnit(Type type, uint32_t ppt) {
assert(type == SECONDS || ppt != 0);
_type = type;
_ppt = ppt;
}
static inline TimeUnit frames(uint32_t srate) { return TimeUnit(FRAMES, srate); }
static inline TimeUnit beats(uint32_t ppqn) { return TimeUnit(BEATS, ppqn); }
static inline TimeUnit seconds() { return TimeUnit(BEATS, std::numeric_limits<uint32_t>::max()); }
inline Type type() const { return _type; }
inline uint32_t ppt() const { return _ppt; }
inline bool operator==(const TimeUnit& rhs) const {
return (_type == rhs._type && _ppt == rhs._ppt);
}
inline bool operator!=(const TimeUnit& rhs) const {
return (_type != rhs._type || _ppt != rhs._ppt);
}
private:
Type _type;
uint32_t _ppt;
};
class TimeStamp {
public:
inline TimeStamp(TimeUnit unit, uint32_t ticks=0, uint32_t subticks=0)
: _ticks(ticks)
, _subticks(subticks)
, _unit(unit)
{}
inline TimeStamp(TimeUnit unit, double dec)
: _ticks(static_cast<uint32_t>(floor(dec)))
, _subticks((dec - floor(dec)) * unit.ppt())
, _unit(unit)
{
assert(dec >= 0);
assert(dec <= std::numeric_limits<uint32_t>::max());
}
inline TimeUnit unit() const { return _unit; }
inline uint32_t ticks() const { return _ticks; }
inline uint32_t subticks() const { return _subticks; }
inline double to_double() const {
return _ticks + (_subticks / static_cast<double>(_unit.ppt()));
}
inline bool is_zero() const {
return _ticks == 0 && _subticks == 0;
}
inline TimeStamp& operator=(const TimeStamp& rhs) {
_ticks = rhs._ticks;
_subticks = rhs._subticks;
_unit = rhs._unit;
return *this;
}
inline TimeStamp& operator=(uint32_t ticks) {
_ticks = ticks;
_subticks = 0;
return *this;
}
inline bool operator==(const TimeStamp& rhs) const {
return _ticks == rhs._ticks
&& _subticks == rhs._subticks
&& _unit == rhs._unit;
}
inline bool operator!=(const TimeStamp& rhs) const {
return ! operator==(rhs);
}
inline bool operator<(const TimeStamp& rhs) const {
assert(_unit == rhs._unit);
return (_ticks < rhs._ticks
|| (_ticks == rhs._ticks && _subticks < rhs._subticks));
}
inline bool operator>(const TimeStamp& rhs) const {
assert(_unit == rhs._unit);
return (_ticks > rhs._ticks
|| (_ticks == rhs._ticks && _subticks > rhs._subticks));
}
inline bool operator<=(const TimeStamp& rhs) const {
return (*this == rhs) || ((*this) < rhs);
}
inline bool operator>=(const TimeStamp& rhs) const {
return (*this == rhs) || ((*this) > rhs);
}
inline TimeStamp& operator+=(const TimeStamp& rhs) {
assert(_unit == rhs._unit);
_ticks += rhs._ticks;
if (_subticks + rhs._subticks <= _unit.ppt()) {
_subticks += rhs._subticks;
} else if (rhs._subticks > 0) {
++_ticks;
_subticks = rhs._subticks + _subticks - _unit.ppt();
}
return *this;
}
inline TimeStamp& operator-=(const TimeStamp& rhs) {
assert(_unit == rhs._unit);
assert(rhs <= *this);
_ticks -= rhs._ticks;
if (_subticks >= rhs._subticks) {
_subticks -= rhs._subticks;
} else if (rhs._subticks > 0) {
--_ticks;
_subticks = _unit.ppt() - (rhs._subticks - _subticks);
}
return *this;
}
inline TimeStamp operator+(const TimeStamp& rhs) const {
assert(_unit == rhs._unit);
TimeStamp result = *this;
result += rhs;
return result;
}
inline TimeStamp operator-(const TimeStamp& rhs) const {
assert(_unit == rhs._unit);
TimeStamp result = *this;
result -= rhs;
return result;
}
private:
uint32_t _ticks;
uint32_t _subticks;
TimeUnit _unit;
};
static inline std::ostream&
operator<<(std::ostream& os, const TimeStamp& t)
{
os << t.ticks() << ":" << t.subticks();
switch (t.unit().type()) {
case TimeUnit::FRAMES:
os << " frames";
break;
case TimeUnit::BEATS:
os << " beats";
break;
case TimeUnit::SECONDS:
os << " seconds";
break;
}
return os;
}
class FrameStamp : public TimeStamp {
public:
inline FrameStamp(uint32_t rate, uint32_t ticks=0, uint32_t subticks=0)
: TimeStamp(TimeUnit(TimeUnit::FRAMES, rate), ticks, subticks)
{}
};
class BeatStamp : public TimeStamp {
public:
inline BeatStamp(uint32_t ppqn, uint32_t ticks=0, uint32_t subticks=0)
: TimeStamp(TimeUnit(TimeUnit::BEATS, ppqn), ticks, subticks)
{}
};
typedef TimeStamp TimeDuration;
} // namespace Raul
#endif // RAUL_TIME_STAMP_HPP
Raul::TimeUnit
A type of time stamp.
Definition: TimeStamp.hpp:33
Raul
Definition: Array.hpp:26
Raul::TimeStamp
A real-time time stamp (possible units: frame, absolute (s), or beat).
Definition: TimeStamp.hpp:80
Raul::TimeUnit::TimeUnit
TimeUnit(Type type, uint32_t ppt)
ppt (parts per tick) is the sample rate for FRAMES, PPQN for BEATS, and ignored for SECONDS...
Definition: TimeStamp.hpp:44