1 /* This file is part of Evoral.
2 * Copyright (C) 2008 David Robillard <http://drobilla.net>
3 * Copyright (C) 2000-2008 Paul Davis
5 * Evoral is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
10 * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef EVORAL_TYPES_HPP
20 #define EVORAL_TYPES_HPP
30 #include "evoral/visibility.h"
32 #include "pbd/debug.h"
36 /** ID of an event (note or other). This must be operable on by glib
39 typedef int32_t event_id_t;
41 /** Musical time: beats relative to some defined origin */
42 class /*LIBEVORAL_API*/ MusicalTime {
44 LIBEVORAL_API static const double PPQN;
46 MusicalTime() : _time(0.0) {}
48 /** Create from a real number of beats. */
49 explicit MusicalTime(double time) : _time(time) {}
51 /** Create from an integer number of beats. */
52 static MusicalTime beats(int32_t beats) {
53 return MusicalTime((double)beats);
56 /** Create from ticks at the standard PPQN. */
57 static MusicalTime ticks(uint32_t ticks) {
58 return MusicalTime(ticks / PPQN);
61 /** Create from ticks at a given rate.
63 * Note this can also be used to create from frames by setting ppqn to the
64 * number of samples per beat.
66 static MusicalTime ticks_at_rate(uint64_t ticks, uint32_t ppqn) {
67 return MusicalTime((double)ticks / (double)ppqn);
70 MusicalTime& operator=(const MusicalTime& other) {
75 MusicalTime round_up_to_beat() const {
76 return Evoral::MusicalTime(ceil(_time));
79 MusicalTime round_down_to_beat() const {
80 return Evoral::MusicalTime(floor(_time));
83 MusicalTime snap_to(const Evoral::MusicalTime& snap) const {
84 return MusicalTime(ceil(_time / snap._time) * snap._time);
87 inline bool operator==(const MusicalTime& b) const {
88 /* Acceptable tolerance is 1 tick. */
89 return fabs(_time - b._time) <= (1.0 / PPQN);
92 inline bool operator==(double t) const {
93 /* Acceptable tolerance is 1 tick. */
94 return fabs(_time - t) <= (1.0 / PPQN);
97 inline bool operator==(int beats) const {
98 /* Acceptable tolerance is 1 tick. */
99 return fabs(_time - beats) <= (1.0 / PPQN);
102 inline bool operator!=(const MusicalTime& b) const {
103 return !operator==(b);
106 inline bool operator<(const MusicalTime& b) const {
107 /* Acceptable tolerance is 1 tick. */
108 if (fabs(_time - b._time) <= (1.0 / PPQN)) {
109 return false; /* Effectively identical. */
111 return _time < b._time;
115 inline bool operator<=(const MusicalTime& b) const {
116 return operator==(b) || operator<(b);
119 inline bool operator>(const MusicalTime& b) const {
120 /* Acceptable tolerance is 1 tick. */
121 if (fabs(_time - b._time) <= (1.0 / PPQN)) {
122 return false; /* Effectively identical. */
124 return _time > b._time;
128 inline bool operator>=(const MusicalTime& b) const {
129 return operator==(b) || operator>(b);
132 inline bool operator<(double b) const {
133 /* Acceptable tolerance is 1 tick. */
134 if (fabs(_time - b) <= (1.0 / PPQN)) {
135 return false; /* Effectively identical. */
141 inline bool operator<=(double b) const {
142 return operator==(b) || operator<(b);
145 inline bool operator>(double b) const {
146 /* Acceptable tolerance is 1 tick. */
147 if (fabs(_time - b) <= (1.0 / PPQN)) {
148 return false; /* Effectively identical. */
154 inline bool operator>=(double b) const {
155 return operator==(b) || operator>(b);
158 MusicalTime operator+(const MusicalTime& b) const {
159 return MusicalTime(_time + b._time);
162 MusicalTime operator-(const MusicalTime& b) const {
163 return MusicalTime(_time - b._time);
166 MusicalTime operator+(double d) const {
167 return MusicalTime(_time + d);
170 MusicalTime operator-(double d) const {
171 return MusicalTime(_time - d);
174 MusicalTime operator-() const {
175 return MusicalTime(-_time);
178 template<typename Number>
179 MusicalTime operator*(Number factor) const {
180 return MusicalTime(_time * factor);
183 MusicalTime& operator+=(const MusicalTime& b) {
188 MusicalTime& operator-=(const MusicalTime& b) {
193 double to_double() const { return _time; }
194 uint64_t to_ticks() const { return lrint(_time * PPQN); }
195 uint64_t to_ticks(uint32_t ppqn) const { return lrint(_time * ppqn); }
197 uint32_t get_beats() const { return floor(_time); }
198 uint32_t get_ticks() const { return (uint32_t)lrint(fmod(_time, 1.0) * PPQN); }
200 bool operator!() const { return _time == 0; }
202 static MusicalTime min() { return MusicalTime(DBL_MIN); }
203 static MusicalTime max() { return MusicalTime(DBL_MAX); }
204 static MusicalTime tick() { return MusicalTime(1.0 / PPQN); }
210 extern LIBEVORAL_API const MusicalTime MaxMusicalTime;
211 extern LIBEVORAL_API const MusicalTime MinMusicalTime;
213 /** Type of an event (opaque, mapped by application) */
214 typedef uint32_t EventType;
217 TIL, several horrible hours later, that sometimes the compiler looks in the
218 namespace of a type (Evoral::MusicalTime in this case) for an operator, and
219 does *NOT* look in the global namespace.
221 C++ is proof that hell exists and we are living in it. In any case, move
222 these to the global namespace and PBD::Property's loopy
223 virtual-method-in-a-template will bite you.
227 operator<<(std::ostream& os, const MusicalTime& t)
234 operator>>(std::istream& is, MusicalTime& t)
238 t = MusicalTime(beats);
242 } // namespace Evoral
246 LIBEVORAL_API extern uint64_t Sequence;
247 LIBEVORAL_API extern uint64_t Note;
248 LIBEVORAL_API extern uint64_t ControlList;
249 LIBEVORAL_API extern uint64_t MusicalTime;
255 struct numeric_limits<Evoral::MusicalTime> {
256 static Evoral::MusicalTime min() { return Evoral::MusicalTime::min(); }
257 static Evoral::MusicalTime max() { return Evoral::MusicalTime::max(); }
261 #endif // EVORAL_TYPES_HPP