Ardour  9.0-pre0-582-g084a23a80d
beats.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017-2018 Paul Davis <paul@linuxaudiosystems.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef TEMPORAL_BEATS_HPP
20 #define TEMPORAL_BEATS_HPP
21 
22 #include <cassert>
23 #include <float.h>
24 #include <math.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 
28 #include <iostream>
29 #include <limits>
30 #include <sstream>
31 
32 #include "pbd/failed_constructor.h"
33 #include "pbd/integer_division.h"
34 #include "pbd/string_convert.h"
35 
36 
37 #include "temporal/visibility.h"
38 #include "temporal/types.h"
39 
40 namespace ARDOUR {
41 class Variant; /* Can stay since LV2 has no way to exchange beats as anything except double */
42 /* these all need fixing to not use ::to_double() */
43 class Track;
44 class MidiStretch;
45 class MidiModel;
46 class AutomationList;
47 class MidiSource;
48 class MidiRegion;
49 class Quantize;
50 }
51 
52 namespace Evoral {
53 template<typename T> class Sequence;
54 }
55 
56 /* XXX hack friends for ::do_double() access ... remove */
57 
58 class QuantizeDialog;
59 class NoteDrag;
60 class NoteCreateDrag;
61 
62 namespace Temporal {
63 
65 class /*LIBTEMPORAL_API*/ Beats {
66 public:
68 
69  Beats() : _ticks(0) {}
70  Beats(const Beats& other) : _ticks(other._ticks) {}
71 
73  explicit Beats(int64_t b, int64_t t) : _ticks ((b*PPQN) + t) {}
74 
76  static Beats from_double (double beats) {
77  double whole;
78  const double frac = modf (beats, &whole);
79  return Beats ((int64_t) whole, (int64_t) rint (frac * PPQN));
80  }
81 
83  static Beats beats(int64_t beats) {
84  return Beats (beats, 0);
85  }
86 
88  static Beats ticks(int64_t ticks) {
89  return Beats (0, ticks);
90  }
91 
99  static Beats ticks_at_rate(int64_t ticks, uint32_t ppqn) {
100  return Beats(ticks / ppqn, (ticks % ppqn) * PPQN / ppqn);
101  }
102 
103  int64_t to_ticks () const { return _ticks; }
104  int64_t to_ticks (uint32_t ppqn) const { return (_ticks * ppqn) / PPQN; }
105 
106  int64_t get_beats () const { return _ticks / PPQN; }
107  int32_t get_ticks () const { return (int32_t) (_ticks % PPQN); }
108 
109  Beats& operator=(double time) {
110  *this = from_double (time);
111  return *this;
112  }
113 
114  Beats& operator=(const Beats& other) {
115  _ticks = other._ticks;
116  return *this;
117  }
118 
119  public:
120  Beats round_up_to_multiple (Beats const & multiple) const {
121  return ticks (((to_ticks() + (multiple.to_ticks() - 1)) / multiple.to_ticks()) * multiple.to_ticks());
122  }
123  Beats round_to_multiple (Beats const & multiple) const {
124  return ticks (((to_ticks() + (int_div_round (multiple.to_ticks(), (int64_t) 2))) / multiple.to_ticks()) * multiple.to_ticks());
125  }
126  Beats round_down_to_multiple (Beats const & multiple) const {
127  return ticks ((to_ticks() / multiple.to_ticks()) * multiple.to_ticks());
128  }
129 
131  return (get_ticks() >= (PPQN/2)) ? Beats (get_beats() + 1, 0) : Beats (get_beats(), 0);
132  }
133 
135  return (get_ticks() == 0) ? *this : Beats(get_beats() + 1, 0);
136  }
137 
139  return Beats(get_beats(), 0);
140  }
141 
142 
143  Beats prev_beat() const {
144  /* always moves backwards even if currently on beat */
145  return Beats (get_beats()-1, 0);
146  }
147 
148  Beats next_beat() const {
149  /* always moves forwards even if currently on beat */
150  return Beats (get_beats()+1, 0);
151  }
152 
153  LIBTEMPORAL_API Beats round_to_subdivision (int subdivision, RoundMode dir) const;
154 
155  Beats abs () const {
156  return ticks (::abs (_ticks));
157  }
158 
159  Beats diff (Beats const & other) const {
160  if (other > *this) {
161  return other - *this;
162  }
163  return *this - other;
164  }
165 
166  inline bool operator==(const Beats& b) const {
167  return _ticks == b._ticks;
168  }
169 
170  inline bool operator==(int beats) const {
171  return get_beats() == beats;
172  }
173 
174  inline bool operator!=(const Beats& b) const {
175  return !operator==(b);
176  }
177 
178  inline bool operator<(const Beats& b) const {
179  return _ticks < b._ticks;
180  }
181 
182  inline bool operator<=(const Beats& b) const {
183  return _ticks <= b._ticks;
184  }
185 
186  inline bool operator>(const Beats& b) const {
187  return _ticks > b._ticks;
188  }
189 
190  inline bool operator>=(const Beats& b) const {
191  return _ticks >= b._ticks;
192  }
193 
194  Beats operator+(const Beats& b) const {
195  return ticks (_ticks + b._ticks);
196  }
197 
198  Beats operator-(const Beats& b) const {
199  return ticks (_ticks - b._ticks);
200  }
201 
202  Beats operator-() const {
203  return ticks (-_ticks);
204  }
205 
206  Beats operator*(int32_t factor) const {return ticks (_ticks * factor); }
207  Beats operator/(int32_t factor) const { return ticks (_ticks / factor);}
208  Beats operator*(ratio_t const & factor) const {return ticks (PBD::muldiv_round (_ticks, factor.numerator(), factor.denominator())); }
209  Beats operator/(ratio_t const & factor) const {return ticks (PBD::muldiv_round (_ticks, factor.denominator(), factor.numerator())); }
210 
211  Beats operator% (Beats const & b) const { return Beats::ticks (_ticks % b.to_ticks());}
212 
213  Beats operator%= (Beats const & b) {
214  _ticks = _ticks % b.to_ticks();
215  return *this;
216  }
217 
218  Beats operator/ (Beats const & other) const {
219  return Beats::ticks (int_div_round (to_ticks(), other.to_ticks()));
220  }
221 
222  Beats operator* (Beats const & other) const {
223  return Beats::ticks (to_ticks () * other.to_ticks());
224  }
225 
226  Beats& operator+=(const Beats& b) {
227  _ticks += b._ticks;
228  return *this;
229  }
230 
231  Beats& operator-=(const Beats& b) {
232  _ticks -= b._ticks;
233  return *this;
234  }
235 
236  bool operator!() const { return _ticks == 0; }
237  explicit operator bool () const { return _ticks != 0; }
238 
239  static Beats one_tick() { return Beats(0, 1); }
240 
241  std::string str () const {
242  std::ostringstream os;
243  os << get_beats() << ':' << get_ticks();
244  return os.str();
245  }
246 
247  protected:
248  int64_t _ticks;
249 
250 };
251 
252 /* Only contexts that really, absolutely need a floating point representation
253  * of a Beats value should ever use this.
254  */
255 
256 class DoubleableBeats : public Beats
257 {
258  public:
259  DoubleableBeats (Beats const & b) : Beats (b) {}
260  double to_double() const { return (double)get_beats() + (get_ticks() / (double)PPQN); }
261 };
262 
263 
264 /*
265  TIL, several horrible hours later, that sometimes the compiler looks in the
266  namespace of a type (Temporal::Beats in this case) for an operator, and
267  does *NOT* look in the global namespace.
268 
269  C++ is proof that hell exists and we are living in it. In any case, move
270  these to the global namespace and PBD::Property's loopy
271  virtual-method-in-a-template will bite you.
272 */
273 
274 LIBTEMPORAL_API std::ostream& operator<<(std::ostream& ostream, const Temporal::Beats& t);
275 LIBTEMPORAL_API std::istream& operator>>(std::istream& istream, Temporal::Beats& b);
276 
277 } // namespace Temporal
278 
279 namespace std {
280  template<>
281  struct numeric_limits<Temporal::Beats> {
283  return Temporal::Beats(std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::min());
284  }
285 
286  /* We don't define min() since this has different behaviour for
287  integral and floating point types, but Beats is used as both
288  an integral and "fractional" value, so the semantics of
289  min() would be unclear.
290 
291  Better to avoid providing a min at all than a confusing one.
292  */
293 
294  /* We must make the number of beats be 1 less than INT32_MAX,
295  * because otherwise adding the PPQN-1 ticks would cause
296  * overflow (the value would be INT32_MAX+((PPQN-1)/PPQN) which
297  * exceeds INT32_MAX.
298  */
299 
300  static Temporal::Beats max() {
301  return Temporal::Beats(std::numeric_limits<int32_t>::max() - 1, Temporal::Beats::PPQN - 1);
302  }
303  };
304 
305 }
306 
307 namespace PBD {
308 
309 template<>
310 inline bool to_string (Temporal::Beats val, std::string & str)
311 {
312  std::ostringstream ostr;
313  ostr << val;
314  str = ostr.str();
315  return true;
316 }
317 
318 template<>
319 inline bool string_to (std::string const & str, Temporal::Beats & val)
320 {
321  std::istringstream istr (str);
322  istr >> val;
323  return (bool) istr;
324 }
325 
326 } /* end namsepace PBD */
327 
328 
329 #endif // TEMPORAL_BEATS_HPP
bool operator!() const
Definition: beats.h:236
int64_t to_ticks(uint32_t ppqn) const
Definition: beats.h:104
Beats round_to_multiple(Beats const &multiple) const
Definition: beats.h:123
Beats operator-() const
Definition: beats.h:202
Beats operator%=(Beats const &b)
Definition: beats.h:213
Beats operator*(ratio_t const &factor) const
Definition: beats.h:208
Beats operator*(int32_t factor) const
Definition: beats.h:206
bool operator!=(const Beats &b) const
Definition: beats.h:174
Beats operator%(Beats const &b) const
Definition: beats.h:211
Beats(int64_t b, int64_t t)
Definition: beats.h:73
Beats & operator=(const Beats &other)
Definition: beats.h:114
int32_t get_ticks() const
Definition: beats.h:107
static Beats ticks(int64_t ticks)
Definition: beats.h:88
static const int32_t PPQN
Definition: beats.h:67
Beats & operator=(double time)
Definition: beats.h:109
Beats operator/(ratio_t const &factor) const
Definition: beats.h:209
int64_t _ticks
Definition: beats.h:248
bool operator<=(const Beats &b) const
Definition: beats.h:182
Beats prev_beat() const
Definition: beats.h:143
Beats & operator+=(const Beats &b)
Definition: beats.h:226
Beats & operator-=(const Beats &b)
Definition: beats.h:231
Beats(const Beats &other)
Definition: beats.h:70
bool operator>(const Beats &b) const
Definition: beats.h:186
std::string str() const
Definition: beats.h:241
Beats operator/(int32_t factor) const
Definition: beats.h:207
Beats next_beat() const
Definition: beats.h:148
static Beats beats(int64_t beats)
Definition: beats.h:83
int64_t to_ticks() const
Definition: beats.h:103
Beats round_to_subdivision(int subdivision, RoundMode dir) const
Beats round_up_to_beat() const
Definition: beats.h:134
int64_t get_beats() const
Definition: beats.h:106
Beats operator-(const Beats &b) const
Definition: beats.h:198
static Beats ticks_at_rate(int64_t ticks, uint32_t ppqn)
Definition: beats.h:99
static Beats from_double(double beats)
Definition: beats.h:76
Beats round_up_to_multiple(Beats const &multiple) const
Definition: beats.h:120
bool operator>=(const Beats &b) const
Definition: beats.h:190
Beats round_to_beat() const
Definition: beats.h:130
Beats round_down_to_multiple(Beats const &multiple) const
Definition: beats.h:126
bool operator==(int beats) const
Definition: beats.h:170
Beats diff(Beats const &other) const
Definition: beats.h:159
bool operator==(const Beats &b) const
Definition: beats.h:166
bool operator<(const Beats &b) const
Definition: beats.h:178
Beats operator+(const Beats &b) const
Definition: beats.h:194
static Beats one_tick()
Definition: beats.h:239
Beats abs() const
Definition: beats.h:155
Beats round_down_to_beat() const
Definition: beats.h:138
double to_double() const
Definition: beats.h:260
DoubleableBeats(Beats const &b)
Definition: beats.h:259
T int_div_round(T x, T y)
Definition: editor.h:86
DebugBits Beats
DebugBits Sequence
Definition: axis_view.h:42
bool to_string(ARDOUR::AnyTime const &at, std::string &str)
int64_t muldiv_round(int64_t v, int64_t n, int64_t d)
bool string_to(std::string const &str, ARDOUR::AnyTime &at)
static const int32_t ticks_per_beat
std::istream & operator>>(std::istream &istream, Temporal::Beats &b)
std::ostream & operator<<(std::ostream &ostream, const Temporal::Beats &t)
static Temporal::Beats lowest()
Definition: beats.h:282
static Temporal::Beats max()
Definition: beats.h:300
#define LIBTEMPORAL_API