Ardour  9.0-pre0-582-g084a23a80d
bbt_time.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2010 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Lesser General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This program is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program; if not, write to the Free Software Foundation,
16  Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 #pragma once
20 
21 #include <ostream>
22 #include <istream>
23 #include <sstream>
24 #include <stdint.h>
25 #include <iomanip>
26 #include <exception>
27 #include <cmath>
28 #include <limits>
29 #include <cstdio>
30 
31 #include "pbd/failed_constructor.h"
32 #include "pbd/string_convert.h"
33 
34 #include "temporal/visibility.h"
35 #include "temporal/types.h"
36 
37 namespace Temporal {
38 
39 struct IllegalBBTTimeException : public std::exception {
40  virtual const char* what() const throw() { return "illegal BBT time (bars or beats were zero, or ticks was too large)"; }
41 };
42 
43 struct BBT_Offset;
44 
47 {
48  /* note that it is illegal for BBT_Time to have bars==0 or
49  * beats==0. The "neutral" or "default" value is 1|1|0
50  */
51 
52  int32_t bars;
53  int32_t beats;
54  int32_t ticks;
55 
56  int64_t as_integer() const;
57  static BBT_Time from_integer (int64_t);
58 
59  bool is_bar() const { return beats == 1 && ticks == 0; }
60  bool is_beat() const { return ticks == 0; }
61 
62  BBT_Time () : bars (1), beats (1), ticks (0) {}
63  BBT_Time (int32_t ba, uint32_t be, uint32_t t) : bars (ba), beats (be), ticks (t) {
64  if (!bars || !beats) {
66  }
67  }
68 
69  bool operator< (const BBT_Time& other) const {
70  return bars < other.bars ||
71  (bars == other.bars && beats < other.beats) ||
72  (bars == other.bars && beats == other.beats && ticks < other.ticks);
73  }
74 
75  bool operator<= (const BBT_Time& other) const {
76  return bars < other.bars ||
77  (bars <= other.bars && beats < other.beats) ||
78  (bars <= other.bars && beats <= other.beats && ticks <= other.ticks);
79  }
80 
81  bool operator> (const BBT_Time& other) const {
82  return bars > other.bars ||
83  (bars == other.bars && beats > other.beats) ||
84  (bars == other.bars && beats == other.beats && ticks > other.ticks);
85  }
86 
87  bool operator>= (const BBT_Time& other) const {
88  return bars > other.bars ||
89  (bars >= other.bars && beats > other.beats) ||
90  (bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
91  }
92 
93  bool operator== (const BBT_Time& other) const {
94  return bars == other.bars && beats == other.beats && ticks == other.ticks;
95  }
96 
97  bool operator!= (const BBT_Time& other) const {
98  return bars != other.bars || beats != other.beats || ticks != other.ticks;
99  }
100 
101  bool operator< (const BBT_Offset& other) const;
102  bool operator<= (const BBT_Offset& other) const;
103  bool operator> (const BBT_Offset& other) const;
104  bool operator>= (const BBT_Offset& other) const;
105  bool operator== (const BBT_Offset& other) const;
106  bool operator!= (const BBT_Offset& other) const;
107 
108  /* it would be nice to provide +,-,* and / operators for BBT_Time but
109  * this math requires knowledge of the meter (time signature) used to
110  * define 1 bar, and so cannot be carried out with only two BBT_Time
111  * values.
112  */
113 
114  BBT_Time round_to_beat () const { return ticks >= (ticks_per_beat/2) ? BBT_Time (bars, beats+1, 0) : BBT_Time (bars, beats, 0); }
115  BBT_Time round_down_to_beat () const { return BBT_Time (bars, beats, 0); }
116  BBT_Time round_up_to_beat () const { return ticks ? BBT_Time (bars, beats+1, 0) : *this; }
117  BBT_Time round_up_to_beat_div (int beat_div) const;
118 
119  /* cannot implement round_to_bar() without knowing meter (time
120  * signature) information, since it requires knowing how many beats
121  * are in a bar, in order to decide if we are closer to the previous or
122  * next bar time.
123  */
124 
126  BBT_Time round_down_to_bar () const { return BBT_Time (bars, 1, 0); }
127  BBT_Time next_bar () const { return (bars == -1) ? BBT_Time (1, 1, 0) : BBT_Time (bars+1, 1, 0); }
128  BBT_Time prev_bar () const { return (bars == 1) ? BBT_Time (-1, 1, 0) : BBT_Time (bars-1, 1, 0); }
129 
130  void print_padded (std::ostream& o) const {
131  o << std::setfill ('0') << std::right
132  << std::setw (3) << bars << "|"
133  << std::setw (2) << beats << "|"
134  << std::setw (4) << ticks;
135  }
136 
137  std::string str () const {
138  std::ostringstream os;
139  os << bars << '|' << beats << '|' << ticks;
140  return os.str ();
141  }
142 
143 };
144 
146 {
147  int32_t bars;
148  int32_t beats;
149  int32_t ticks;
150 
151  /* this is a variant for which bars==0 and/or beats==0 is legal. It
152  * represents an offset from a given BBT_Time and is used when doing
153  * add/subtract operations on a BBT_Time.
154  */
155 
156  BBT_Offset () : bars (0), beats (0), ticks (0) {}
157  BBT_Offset (int32_t ba, uint32_t be, uint32_t t) : bars (ba), beats (be), ticks (t) {}
158  BBT_Offset (BBT_Time const & bbt) : bars (bbt.bars), beats (bbt.beats), ticks (bbt.ticks) {}
159  explicit BBT_Offset (double beats);
160 
161  /* unlike BBT_Time, we can define +,-,* and / operators for BBT_Offset
162  * because there is no requirement that the result is "well-formed" or
163  * reflect the structure of a tempo map. It is just as valid to talk
164  * about an offset of 18 beats as an offset of 4 bars and 2 beats.
165  */
166 
167  BBT_Offset operator+(const BBT_Offset& other) const {
168  return BBT_Offset (bars+other.bars, beats+other.beats, ticks+other.ticks);
169  }
170 
172  return BBT_Offset (-bars, -beats, -ticks);
173  }
174 
175  BBT_Offset operator-(const BBT_Offset& other) const {
176  return BBT_Offset (bars-other.bars, beats-other.beats, ticks-other.ticks);
177  }
178 
179  BBT_Offset & operator+=(const BBT_Offset& other) {
180  bars += other.bars;
181  beats += other.beats;
182  ticks += other.ticks;
183  return *this;
184  }
185 
186  BBT_Offset & operator-=(const BBT_Offset& other) {
187  bars -= other.bars;
188  beats -= other.beats;
189  ticks -= other.ticks;
190  return *this;
191  }
192 
193  BBT_Offset & operator*=(int factor) {
194  bars *= factor;
195  beats *= factor;
196  ticks *= factor;
197  return *this;
198  }
199 
200  BBT_Offset & operator*=(double factor) {
201  bars = (int32_t) lrint (bars * factor);
202  beats = (int32_t) lrint (beats * factor);
203  ticks = (int32_t) lrint (ticks * factor);
204  return *this;
205  }
206 
207  BBT_Offset & operator/=(int factor) {
208  bars /= factor;
209  beats /= factor;
210  ticks /= factor;
211  return *this;
212  }
213 
214  BBT_Offset & operator/=(double factor) {
215  bars = (int32_t) lrint (bars / factor);
216  beats = (int32_t) lrint (beats / factor);
217  ticks = (int32_t) lrint (ticks / factor);
218  return *this;
219  }
220 
221  bool operator< (const BBT_Offset& other) const {
222  return bars < other.bars ||
223  (bars == other.bars && beats < other.beats) ||
224  (bars == other.bars && beats == other.beats && ticks < other.ticks);
225  }
226 
227  bool operator<= (const BBT_Offset& other) const {
228  return bars < other.bars ||
229  (bars <= other.bars && beats <= other.beats) ||
230  (bars <= other.bars && beats <= other.beats && ticks <= other.ticks);
231  }
232 
233  bool operator> (const BBT_Offset& other) const {
234  return bars > other.bars ||
235  (bars == other.bars && beats > other.beats) ||
236  (bars == other.bars && beats == other.beats && ticks > other.ticks);
237  }
238 
239  bool operator>= (const BBT_Offset& other) const {
240  return bars > other.bars ||
241  (bars >= other.bars && beats >= other.beats) ||
242  (bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
243  }
244 
245  bool operator== (const BBT_Offset& other) const {
246  return bars == other.bars && beats == other.beats && ticks == other.ticks;
247  }
248 
249  bool operator!= (const BBT_Offset& other) const {
250  return bars != other.bars || beats != other.beats || ticks != other.ticks;
251  }
252 
253  operator bool() const {
254  return bars == 0 && beats == 0 && ticks == 0;
255  }
256 
257  std::string str () const {
258  std::ostringstream os;
259  os << bars << '|' << beats << '|' << ticks;
260  return os.str ();
261  }
262 };
263 
265  return Temporal::BBT_Offset (a.bars - b.bars, a.beats - b.beats, a.ticks - b.ticks);
266 }
267 
268 inline bool
269 BBT_Time::operator< (const BBT_Offset& other) const
270 {
271  return bars < other.bars ||
272  (bars == other.bars && beats < other.beats) ||
273  (bars == other.bars && beats == other.beats && ticks < other.ticks);
274 }
275 
276 inline bool
277 BBT_Time::operator<= (const BBT_Offset& other) const
278 {
279  return bars < other.bars ||
280  (bars <= other.bars && beats <= other.beats) ||
281  (bars <= other.bars && beats <= other.beats && ticks <= other.ticks);
282 }
283 
284 inline bool
285 BBT_Time::operator> (const BBT_Offset& other) const
286 {
287  return bars > other.bars ||
288  (bars == other.bars && beats > other.beats) ||
289  (bars == other.bars && beats == other.beats && ticks > other.ticks);
290 }
291 
292 inline bool
294 {
295  return bars > other.bars ||
296  (bars >= other.bars && beats >= other.beats) ||
297  (bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
298 }
299 
300 inline bool
302 {
303  return bars == other.bars && beats == other.beats && ticks == other.ticks;
304 }
305 
306 inline bool
308 {
309  return bars != other.bars || beats != other.beats || ticks != other.ticks;
310 }
311 
312 } /* end of namespace Temporal */
313 
314 /* Putting these into std:: seems wrong, but g++ is unable to find them
315  * otherwise
316  */
317 
318 namespace std {
319 
320 LIBTEMPORAL_API std::ostream& operator<< (std::ostream& o, Temporal::BBT_Time const & bbt);
321 LIBTEMPORAL_API std::ostream& operator<< (std::ostream& o, Temporal::BBT_Offset const & bbt);
322 LIBTEMPORAL_API std::istream& operator>> (std::istream& i, Temporal::BBT_Time& bbt);
323 LIBTEMPORAL_API std::istream& operator>> (std::istream& i, Temporal::BBT_Offset& bbt);
324 
325 template<>
326 struct numeric_limits<Temporal::BBT_Time> {
328  return Temporal::BBT_Time(1, 1, 0);
329  }
331  return Temporal::BBT_Time(1, 1, 0);
332  }
333 
335  return Temporal::BBT_Time(std::numeric_limits<int32_t>::max(),
336  std::numeric_limits<int32_t>::max(),
337  std::numeric_limits<int32_t>::max());
338  }
339 };
340 
341 template<>
342 struct numeric_limits<Temporal::BBT_Offset> {
344  return Temporal::BBT_Time(0, 0, 0);
345  }
346 
348  return Temporal::BBT_Time(0, 0, 0);
349  }
350 
352  return Temporal::BBT_Time(std::numeric_limits<int32_t>::max(),
353  std::numeric_limits<int32_t>::max(),
354  std::numeric_limits<int32_t>::max());
355  }
356 };
357 
358 
359 } /* end of namespace std */
360 
361 namespace PBD {
362 
363 template<>
364 inline bool to_string (Temporal::BBT_Time val, std::string & str)
365 {
366  std::ostringstream ostr;
367  ostr << val;
368  str = ostr.str();
369  return true;
370 }
371 
372 template<>
373 inline std::string to_string (Temporal::BBT_Time val)
374 {
375  std::ostringstream ostr;
376  ostr << val;
377  return ostr.str();
378 }
379 
380 template<>
381 inline bool string_to (std::string const & str, Temporal::BBT_Time & val)
382 {
383  std::istringstream istr (str);
384  istr >> val;
385  return (bool) istr;
386 }
387 
388 template<>
389 inline Temporal::BBT_Time string_to (std::string const & str)
390 {
391  Temporal::BBT_Time tmp;
392  string_to (str, tmp);
393  return tmp;
394 }
395 
396 template<>
397 inline bool to_string (Temporal::BBT_Offset val, std::string & str)
398 {
399  std::ostringstream ostr;
400  ostr << val;
401  str = ostr.str();
402  return true;
403 }
404 
405 template<>
406 inline std::string to_string (Temporal::BBT_Offset val)
407 {
408  std::ostringstream ostr;
409  ostr << val;
410  return ostr.str();
411 }
412 
413 template<>
414 inline bool string_to (std::string const & str, Temporal::BBT_Offset & val)
415 {
416  std::istringstream istr (str);
417  istr >> val;
418  return (bool) istr;
419 }
420 
421 template<>
422 inline Temporal::BBT_Offset string_to (std::string const & str)
423 {
425  string_to (str, tmp);
426  return tmp;
427 }
428 
429 } /* end namespace PBD */
430 
Definition: axis_view.h:42
bool to_string(ARDOUR::AnyTime const &at, std::string &str)
bool string_to(std::string const &str, ARDOUR::AnyTime &at)
BBT_Offset bbt_delta(Temporal::BBT_Time const &a, Temporal::BBT_Time const &b)
Definition: bbt_time.h:264
static const int32_t ticks_per_beat
bool operator==(const ProcessorSelection &a, const ProcessorSelection &b)
BBT_Offset operator+(const BBT_Offset &other) const
Definition: bbt_time.h:167
BBT_Offset & operator/=(double factor)
Definition: bbt_time.h:214
BBT_Offset & operator*=(double factor)
Definition: bbt_time.h:200
BBT_Offset & operator/=(int factor)
Definition: bbt_time.h:207
BBT_Offset(int32_t ba, uint32_t be, uint32_t t)
Definition: bbt_time.h:157
BBT_Offset & operator+=(const BBT_Offset &other)
Definition: bbt_time.h:179
BBT_Offset operator-(const BBT_Offset &other) const
Definition: bbt_time.h:175
std::string str() const
Definition: bbt_time.h:257
BBT_Offset operator-() const
Definition: bbt_time.h:171
BBT_Offset & operator*=(int factor)
Definition: bbt_time.h:193
BBT_Offset(BBT_Time const &bbt)
Definition: bbt_time.h:158
BBT_Offset & operator-=(const BBT_Offset &other)
Definition: bbt_time.h:186
BBT_Offset(double beats)
BBT_Time round_up_to_beat() const
Definition: bbt_time.h:116
void print_padded(std::ostream &o) const
Definition: bbt_time.h:130
int64_t as_integer() const
BBT_Time(int32_t ba, uint32_t be, uint32_t t)
Definition: bbt_time.h:63
BBT_Time round_down_to_beat() const
Definition: bbt_time.h:115
BBT_Time round_up_to_beat_div(int beat_div) const
bool operator<(const BBT_Time &other) const
Definition: bbt_time.h:69
BBT_Time round_down_to_bar() const
Definition: bbt_time.h:126
static BBT_Time from_integer(int64_t)
std::string str() const
Definition: bbt_time.h:137
bool operator<=(const BBT_Time &other) const
Definition: bbt_time.h:75
BBT_Time round_to_beat() const
Definition: bbt_time.h:114
bool is_bar() const
Definition: bbt_time.h:59
BBT_Time round_up_to_bar() const
BBT_Time prev_bar() const
Definition: bbt_time.h:128
bool operator==(const BBT_Time &other) const
Definition: bbt_time.h:93
bool operator>(const BBT_Time &other) const
Definition: bbt_time.h:81
bool is_beat() const
Definition: bbt_time.h:60
bool operator>=(const BBT_Time &other) const
Definition: bbt_time.h:87
bool operator!=(const BBT_Time &other) const
Definition: bbt_time.h:97
BBT_Time next_bar() const
Definition: bbt_time.h:127
virtual const char * what() const
Definition: bbt_time.h:40
static Temporal::BBT_Offset min()
Definition: bbt_time.h:347
static Temporal::BBT_Time max()
Definition: bbt_time.h:351
static Temporal::BBT_Offset lowest()
Definition: bbt_time.h:343
static Temporal::BBT_Time min()
Definition: bbt_time.h:330
static Temporal::BBT_Time max()
Definition: bbt_time.h:334
static Temporal::BBT_Time lowest()
Definition: bbt_time.h:327
#define LIBTEMPORAL_API