ardour
Beats.hpp
Go to the documentation of this file.
1 /* This file is part of Evoral.
2  * Copyright (C) 2008-2015 David Robillard <http://drobilla.net>
3  * Copyright (C) 2000-2008 Paul Davis
4  *
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
8  * version.
9  *
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.
13  *
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
17  */
18 
19 #ifndef EVORAL_BEATS_HPP
20 #define EVORAL_BEATS_HPP
21 
22 #include <float.h>
23 #include <math.h>
24 #include <stdint.h>
25 
26 #include <iostream>
27 #include <limits>
28 
29 #include "evoral/visibility.h"
30 
31 namespace Evoral {
32 
34 class /*LIBEVORAL_API*/ Beats {
35 public:
36  LIBEVORAL_API static const double PPQN;
37 
38  Beats() : _time(0.0) {}
39 
41  explicit Beats(double time) : _time(time) {}
42 
44  static Beats beats(int32_t beats) {
45  return Beats((double)beats);
46  }
47 
49  static Beats ticks(uint32_t ticks) {
50  return Beats(ticks / PPQN);
51  }
52 
58  static Beats ticks_at_rate(uint64_t ticks, uint32_t ppqn) {
59  return Beats((double)ticks / (double)ppqn);
60  }
61 
62  Beats& operator=(const Beats& other) {
63  _time = other._time;
64  return *this;
65  }
66 
68  return Evoral::Beats(ceil(_time));
69  }
70 
72  return Evoral::Beats(floor(_time));
73  }
74 
75  Beats snap_to(const Evoral::Beats& snap) const {
76  return Beats(ceil(_time / snap._time) * snap._time);
77  }
78 
79  inline bool operator==(const Beats& b) const {
80  /* Acceptable tolerance is 1 tick. */
81  return fabs(_time - b._time) <= (1.0 / PPQN);
82  }
83 
84  inline bool operator==(double t) const {
85  /* Acceptable tolerance is 1 tick. */
86  return fabs(_time - t) <= (1.0 / PPQN);
87  }
88 
89  inline bool operator==(int beats) const {
90  /* Acceptable tolerance is 1 tick. */
91  return fabs(_time - beats) <= (1.0 / PPQN);
92  }
93 
94  inline bool operator!=(const Beats& b) const {
95  return !operator==(b);
96  }
97 
98  inline bool operator<(const Beats& b) const {
99  /* Acceptable tolerance is 1 tick. */
100  if (fabs(_time - b._time) <= (1.0 / PPQN)) {
101  return false; /* Effectively identical. */
102  } else {
103  return _time < b._time;
104  }
105  }
106 
107  inline bool operator<=(const Beats& b) const {
108  return operator==(b) || operator<(b);
109  }
110 
111  inline bool operator>(const Beats& b) const {
112  /* Acceptable tolerance is 1 tick. */
113  if (fabs(_time - b._time) <= (1.0 / PPQN)) {
114  return false; /* Effectively identical. */
115  } else {
116  return _time > b._time;
117  }
118  }
119 
120  inline bool operator>=(const Beats& b) const {
121  return operator==(b) || operator>(b);
122  }
123 
124  inline bool operator<(double b) const {
125  /* Acceptable tolerance is 1 tick. */
126  if (fabs(_time - b) <= (1.0 / PPQN)) {
127  return false; /* Effectively identical. */
128  } else {
129  return _time < b;
130  }
131  }
132 
133  inline bool operator<=(double b) const {
134  return operator==(b) || operator<(b);
135  }
136 
137  inline bool operator>(double b) const {
138  /* Acceptable tolerance is 1 tick. */
139  if (fabs(_time - b) <= (1.0 / PPQN)) {
140  return false; /* Effectively identical. */
141  } else {
142  return _time > b;
143  }
144  }
145 
146  inline bool operator>=(double b) const {
147  return operator==(b) || operator>(b);
148  }
149 
150  Beats operator+(const Beats& b) const {
151  return Beats(_time + b._time);
152  }
153 
154  Beats operator-(const Beats& b) const {
155  return Beats(_time - b._time);
156  }
157 
158  Beats operator+(double d) const {
159  return Beats(_time + d);
160  }
161 
162  Beats operator-(double d) const {
163  return Beats(_time - d);
164  }
165 
166  Beats operator-() const {
167  return Beats(-_time);
168  }
169 
170  template<typename Number>
171  Beats operator*(Number factor) const {
172  return Beats(_time * factor);
173  }
174 
175  Beats& operator+=(const Beats& b) {
176  _time += b._time;
177  return *this;
178  }
179 
180  Beats& operator-=(const Beats& b) {
181  _time -= b._time;
182  return *this;
183  }
184 
185  double to_double() const { return _time; }
186  uint64_t to_ticks() const { return lrint(_time * PPQN); }
187  uint64_t to_ticks(uint32_t ppqn) const { return lrint(_time * ppqn); }
188 
189  uint32_t get_beats() const { return floor(_time); }
190  uint32_t get_ticks() const { return (uint32_t)lrint(fmod(_time, 1.0) * PPQN); }
191 
192  bool operator!() const { return _time == 0; }
193 
194  static Beats min() { return Beats(DBL_MIN); }
195  static Beats max() { return Beats(DBL_MAX); }
196  static Beats tick() { return Beats(1.0 / PPQN); }
197 
198 private:
199  double _time;
200 };
201 
202 extern LIBEVORAL_API const Beats MaxBeats;
203 extern LIBEVORAL_API const Beats MinBeats;
204 
205 /*
206  TIL, several horrible hours later, that sometimes the compiler looks in the
207  namespace of a type (Evoral::Beats in this case) for an operator, and
208  does *NOT* look in the global namespace.
209 
210  C++ is proof that hell exists and we are living in it. In any case, move
211  these to the global namespace and PBD::Property's loopy
212  virtual-method-in-a-template will bite you.
213 */
214 
215 inline std::ostream&
216 operator<<(std::ostream& os, const Beats& t)
217 {
218  os << t.to_double();
219  return os;
220 }
221 
222 inline std::istream&
223 operator>>(std::istream& is, Beats& t)
224 {
225  double beats;
226  is >> beats;
227  t = Beats(beats);
228  return is;
229 }
230 
231 } // namespace Evoral
232 
233 namespace PBD {
234  namespace DEBUG {
235  LIBEVORAL_API extern uint64_t Beats;
236  }
237 }
238 
239 namespace std {
240  template<>
241  struct numeric_limits<Evoral::Beats> {
242  static Evoral::Beats min() { return Evoral::Beats::min(); }
243  static Evoral::Beats max() { return Evoral::Beats::max(); }
244  };
245 }
246 
247 #endif // EVORAL_BEATS_HPP
bool operator!() const
Definition: Beats.hpp:192
static LIBEVORAL_API const double PPQN
Definition: Beats.hpp:36
Beats round_down_to_beat() const
Definition: Beats.hpp:71
uint32_t get_ticks() const
Definition: Beats.hpp:190
bool operator<=(double b) const
Definition: Beats.hpp:133
LIBEVORAL_API const Beats MaxBeats
Definition: types.cpp:26
Beats & operator+=(const Beats &b)
Definition: Beats.hpp:175
#define DEBUG(format,...)
static Beats min()
Definition: Beats.hpp:194
Beats & operator=(const Beats &other)
Definition: Beats.hpp:62
Definition: Beats.hpp:239
bool operator==(double t) const
Definition: Beats.hpp:84
#define LIBEVORAL_API
Definition: visibility.h:45
static Evoral::Beats min()
Definition: Beats.hpp:242
std::ostream & operator<<(std::ostream &os, const Beats &t)
Definition: Beats.hpp:216
Beats & operator-=(const Beats &b)
Definition: Beats.hpp:180
LIBEVORAL_API const Beats MinBeats
Definition: types.cpp:27
bool operator==(int beats) const
Definition: Beats.hpp:89
bool operator>(const Beats &b) const
Definition: Beats.hpp:111
bool operator>=(const Beats &b) const
Definition: Beats.hpp:120
bool operator<(const Beats &b) const
Definition: Beats.hpp:98
bool operator>(double b) const
Definition: Beats.hpp:137
bool operator!=(const Beats &b) const
Definition: Beats.hpp:94
Beats(double time)
Definition: Beats.hpp:41
std::istream & operator>>(std::istream &is, Beats &t)
Definition: Beats.hpp:223
static Beats ticks_at_rate(uint64_t ticks, uint32_t ppqn)
Definition: Beats.hpp:58
bool operator==(const Beats &b) const
Definition: Beats.hpp:79
static Beats beats(int32_t beats)
Definition: Beats.hpp:44
bool operator<(double b) const
Definition: Beats.hpp:124
uint64_t to_ticks() const
Definition: Beats.hpp:186
bool operator<=(const Beats &b) const
Definition: Beats.hpp:107
static Beats tick()
Definition: Beats.hpp:196
Beats operator-() const
Definition: Beats.hpp:166
static Beats ticks(uint32_t ticks)
Definition: Beats.hpp:49
uint32_t get_beats() const
Definition: Beats.hpp:189
static Evoral::Beats max()
Definition: Beats.hpp:243
Beats round_up_to_beat() const
Definition: Beats.hpp:67
static Beats max()
Definition: Beats.hpp:195
Beats operator+(const Beats &b) const
Definition: Beats.hpp:150
Beats snap_to(const Evoral::Beats &snap) const
Definition: Beats.hpp:75
Beats operator-(double d) const
Definition: Beats.hpp:162
Beats operator*(Number factor) const
Definition: Beats.hpp:171
bool operator>=(double b) const
Definition: Beats.hpp:146
Definition: debug.h:30
double to_double() const
Definition: Beats.hpp:185
uint64_t to_ticks(uint32_t ppqn) const
Definition: Beats.hpp:187
LIBEVORAL_API uint64_t Beats
Beats operator+(double d) const
Definition: Beats.hpp:158
Beats operator-(const Beats &b) const
Definition: Beats.hpp:154
double _time
Definition: Beats.hpp:199