933ee65dc1253d283b07f43e45332409b64dc0b5
[ardour.git] / nutemp / t.h
1 #ifndef __ardour_tempo_h__
2 #define __ardour_tempo_h__
3
4 #include <list>
5 #include <string>
6 #include <vector>
7 #include <cmath>
8 #include <exception>
9
10 #include <glibmm/threads.h>
11
12 #include "evoral/Beats.hpp"
13
14 #include "ardour/ardour.h"
15 #include "ardour/superclock.h"
16
17 #include "timecode/bbt_time.h"
18
19 namespace ARDOUR {
20
21 class Meter;
22 class TempoMap;
23
24 /** Tempo, the speed at which musical time progresses (BPM).
25  */
26
27 class LIBARDOUR_API Tempo {
28   public:
29         /**
30          * @param npm Note Types per minute
31          * @param type Note Type (default `4': quarter note)
32          */
33         Tempo (double npm, int type = 4) : _superclocks_per_note_type (double_npm_to_sc (npm)), _note_type (type) {}
34
35         /* these two methods should only be used to show and collect information to the user (for whom
36          * bpm as a floating point number is the obvious representation)
37          */
38         double note_types_per_minute () const { return (superclock_ticks_per_second * 60.0) / _superclocks_per_note_type; }
39         void set_note_types_per_minute (double npm) { _superclocks_per_note_type = double_npm_to_sc (npm); }
40
41         int note_type () const { return _note_type; }
42
43         superclock_t superclocks_per_note_type () const {
44                 return _superclocks_per_note_type;
45         }
46         superclock_t superclocks_per_note_type (int note_type) const {
47                 return (_superclocks_per_note_type * _note_type) / note_type;
48         }
49         superclock_t superclocks_per_quarter_note () const {
50                 return superclocks_per_note_type (4);
51         }
52
53         Tempo& operator=(Tempo const& other) {
54                 if (&other != this) {
55                         _superclocks_per_note_type = other._superclocks_per_note_type;
56                         _note_type = other._note_type;
57                 }
58                 return *this;
59         }
60
61   protected:
62         superclock_t _superclocks_per_note_type;
63         int8_t       _note_type;
64
65         static inline double       sc_to_double_npm (superclock_t sc) { return (superclock_ticks_per_second * 60.0) / sc; }
66         static inline superclock_t double_npm_to_sc (double npm) { return llrint ((superclock_ticks_per_second / npm) * 60.0); }
67 };
68
69 /** Meter, or time signature (subdivisions per bar, and which note type is a single subdivision). */
70 class LIBARDOUR_API Meter {
71   public:
72         Meter (int8_t dpb, int8_t nv) : _note_value (nv), _divisions_per_bar (dpb) {}
73
74         int divisions_per_bar () const { return _divisions_per_bar; }
75         int note_value() const { return _note_value; }
76
77         inline bool operator==(const Meter& other) { return _divisions_per_bar == other.divisions_per_bar() && _note_value == other.note_value(); }
78         inline bool operator!=(const Meter& other) { return _divisions_per_bar != other.divisions_per_bar() || _note_value != other.note_value(); }
79
80         Meter& operator=(Meter const & other) {
81                 if (&other != this) {
82                         _divisions_per_bar = other._divisions_per_bar;
83                         _note_value = other._note_value;
84                 }
85                 return *this;
86         }
87
88         Timecode::BBT_Time   bbt_add (Timecode::BBT_Time const & bbt, Timecode::BBT_Offset const & add) const;
89         Timecode::BBT_Time   bbt_subtract (Timecode::BBT_Time const & bbt, Timecode::BBT_Offset const & sub) const;
90         Timecode::BBT_Offset bbt_delta (Timecode::BBT_Time const & bbt, Timecode::BBT_Time const & sub) const;
91
92         Timecode::BBT_Time round_up_to_bar (Timecode::BBT_Time const &) const;
93         Timecode::BBT_Time round_down_to_bar (Timecode::BBT_Time const &) const;
94         Timecode::BBT_Time round_to_bar (Timecode::BBT_Time const &) const;
95
96         Evoral::Beats to_quarters (Timecode::BBT_Offset const &) const;
97
98   protected:
99         /** The type of "note" that a division represents.  For example, 4 is
100             a quarter (crotchet) note, 8 is an eighth (quaver) note, etc.
101         */
102         int8_t _note_value;
103         /* how many of '_note_value' make up a bar or measure */
104         int8_t _divisions_per_bar;
105 };
106
107 /** Helper class to keep track of the Meter *AND* Tempo in effect
108     at a given point in time.
109 */
110 class LIBARDOUR_API TempoMetric : public Tempo, public Meter {
111   public:
112         TempoMetric (Tempo const & t, Meter const & m, bool ramp) : Tempo (t), Meter (m), _c_per_quarter (0.0), _c_per_superclock (0.0), _ramped (ramp) {}
113         ~TempoMetric () {}
114
115         double c_per_superclock () const { return _c_per_superclock; }
116         double c_per_quarter () const { return _c_per_quarter; }
117
118         void compute_c_superclock (framecnt_t sr, superclock_t end_superclocks_per_note_type, superclock_t duration);
119         void compute_c_quarters (framecnt_t sr, superclock_t end_superclocks_per_note_type, Evoral::Beats const & duration);
120
121         superclock_t superclocks_per_bar (framecnt_t sr) const;
122         superclock_t superclocks_per_grid (framecnt_t sr) const;
123
124         superclock_t superclock_at_qn (Evoral::Beats const & qn) const;
125         superclock_t superclock_per_note_type_at_superclock (superclock_t) const;
126
127         bool ramped () const { return _ramped; }
128         void set_ramped (bool yn) { _ramped = yn; } /* caller must mark something dirty to force recompute */
129
130   private:
131         double _c_per_quarter;
132         double _c_per_superclock;
133         bool   _ramped;
134 };
135
136 /** Tempo Map - mapping of timecode to musical time.
137  * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo
138  */
139
140 /* TempoMap concepts
141
142    we have several different ways of talking about time:
143
144    * PULSE : whole notes, just because. These are linearly related to any other
145              note type, so if you know a number of pulses (whole notes), you
146              know the corresponding number of any other note type (e.g. quarter
147              notes).
148
149    * QUARTER NOTES : just what the name says. A lot of MIDI software and
150                      concepts assume that a "beat" is a quarter-note.
151
152    * BEAT : a fraction of a PULSE. Defined by the meter in effect, so requires
153             meter (time signature) information to convert to/from PULSE or QUARTER NOTES.
154             In a 5/8 time, a BEAT is 1/8th note. In a 4/4 time, a beat is quarter note.
155             This means that measuring time in BEATS is potentially non-linear (if
156             the time signature changes, there will be a different number of BEATS
157             corresponding to a given time in any other unit).
158
159    * SUPERCLOCK : a very high resolution clock whose frequency
160                   has as factors all common sample rates and all common note
161                   type divisors. Related to MINUTES or SAMPLES only when a
162                   sample rate is known. Related to PULSE or QUARTER NOTES only
163                   when a tempo is known.
164
165    * MINUTES : wallclock time measurement. related to SAMPLES or SUPERCLOCK
166                only when a sample rate is known.
167
168
169    * SAMPLES : audio time measurement. Related to MINUTES or SUPERCLOCK only
170                when a sample rate is known
171
172    * BBT : bars|beats|ticks ... linearly related to BEATS but with the added
173            semantics of bars ("measures") added, in which beats are broken up
174            into groups of bars ("measures"). Requires meter (time signature)
175            information to compute to/from a given BEATS value. Contains no
176            additional time information compared to BEATS, but does have
177            additional semantic information.
178
179   Nick sez: not every note onset is on a tick
180   Paul wonders: if it's 8 samples off, does it matter?
181   Nick sez: it should not phase with existing audio
182
183  */
184
185 class LIBARDOUR_API TempoMapPoint
186 {
187   public:
188         enum Flag {
189                 ExplicitTempo = 0x1,
190                 ExplicitMeter = 0x2,
191         };
192
193         TempoMapPoint (Flag f, Tempo const& t, Meter const& m, superclock_t sc, Evoral::Beats const & q, Timecode::BBT_Time const & bbt, PositionLockStyle psl, bool ramp = false)
194                 : _flags (f), _explicit (t, m, psl, ramp), _sclock (sc), _quarters (q), _bbt (bbt), _dirty (true) {}
195         TempoMapPoint (TempoMapPoint const & tmp, superclock_t sc, Evoral::Beats const & q, Timecode::BBT_Time const & bbt)
196                 : _flags (Flag (0)), _reference (&tmp), _sclock (sc), _quarters (q), _bbt (bbt), _dirty (true) {}
197         ~TempoMapPoint () {}
198
199         bool is_explicit() const { return _flags != Flag (0); }
200         bool is_implicit() const { return _flags == Flag (0); }
201
202         superclock_t superclocks_per_note_type (int8_t note_type) const {
203                 if (is_explicit()) {
204                         return _explicit.metric.superclocks_per_note_type (note_type);
205                 }
206                 return _reference->superclocks_per_note_type (note_type);
207         }
208
209         struct BadTempoMetricLookup : public std::exception {
210                 virtual const char* what() const throw() { return "cannot obtain non-const Metric from implicit map point"; }
211         };
212
213         bool                dirty()  const { return _dirty; }
214
215         superclock_t        sclock() const      { return _sclock; }
216         Evoral::Beats const & quarters() const  { return _quarters; }
217         Timecode::BBT_Time  const & bbt() const { return _bbt; }
218         bool                ramped() const      { return metric().ramped(); }
219         TempoMetric const & metric() const      { return is_explicit() ? _explicit.metric : _reference->metric(); }
220         PositionLockStyle   lock_style() const  { return is_explicit() ? _explicit.lock_style : _reference->lock_style(); }
221
222         void compute_c_superclock (framecnt_t sr, superclock_t end_superclocks_per_note_type, superclock_t duration) { if (is_explicit()) { _explicit.metric.compute_c_superclock (sr, end_superclocks_per_note_type, duration); } }
223         void compute_c_quarters (framecnt_t sr, superclock_t end_superclocks_per_note_type, Evoral::Beats const & duration) { if (is_explicit()) { _explicit.metric.compute_c_quarters (sr, end_superclocks_per_note_type, duration); } }
224
225         /* None of these properties can be set for an Implicit point, because
226          * they are determined by the TempoMapPoint pointed to by _reference.
227          */
228
229         void set_sclock (superclock_t  sc) { if (is_explicit()) { _sclock = sc; _dirty = true; } }
230         void set_quarters (Evoral::Beats const & q) { if (is_explicit()) { _quarters = q; _dirty = true;  } }
231         void set_bbt (Timecode::BBT_Time const & bbt) {  if (is_explicit()) { _bbt = bbt; _dirty = true;  } }
232         void set_dirty (bool yn) { if (is_explicit()) { _dirty = yn; } }
233         void set_lock_style (PositionLockStyle psl) {  if (is_explicit()) { _explicit.lock_style = psl; _dirty = true; } }
234
235         void make_explicit (Flag f) {
236                 _flags = Flag (_flags|f);
237                 /* since _metric and _reference are part of an anonymous union,
238                    avoid possible compiler glitches by copying to a stack
239                    variable first, then assign.
240                 */
241                 TempoMetric tm (_explicit.metric);
242                 _explicit.metric = tm;
243                 _dirty = true;
244         }
245
246         void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
247
248         Evoral::Beats quarters_at (superclock_t sc) const;
249         Evoral::Beats quarters_at (Timecode::BBT_Time const &) const;
250
251         Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
252
253 #if 0
254         XMLNode& get_state() const;
255         int set_state (XMLNode const&, int version);
256 #endif
257
258         struct SuperClockComparator {
259                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
260         };
261
262         struct QuarterComparator {
263                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
264         };
265
266         struct BBTComparator {
267                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
268         };
269
270   protected:
271         friend class TempoMap;
272         void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
273
274   private:
275         struct ExplicitInfo {
276                 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
277
278                 TempoMetric       metric;
279                 PositionLockStyle lock_style;
280         };
281
282         Flag                  _flags;
283         union {
284                 TempoMapPoint const * _reference;
285                 ExplicitInfo          _explicit;
286         };
287         superclock_t          _sclock;
288         Evoral::Beats         _quarters;
289         Timecode::BBT_Time    _bbt;
290         bool                  _dirty;
291 };
292
293 typedef std::list<TempoMapPoint> TempoMapPoints;
294
295 class LIBARDOUR_API TempoMap
296 {
297    public:
298         TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr);
299
300         void set_sample_rate (framecnt_t sr);
301         framecnt_t sample_rate() const { return _sample_rate; }
302
303         void remove_explicit_point (superclock_t);
304
305         bool move_to (superclock_t current, superclock_t destination, bool push = false);
306
307         bool set_tempo_and_meter (Tempo const &, Meter const &, superclock_t, bool ramp, bool flexible);
308
309         bool set_tempo (Tempo const &, Timecode::BBT_Time const &, bool ramp = false);
310         bool set_tempo (Tempo const &, superclock_t, bool ramp = false);
311
312         bool set_meter (Meter const &, Timecode::BBT_Time const &);
313         bool set_meter (Meter const &, superclock_t);
314
315         Meter const & meter_at (superclock_t sc) const;
316         Meter const & meter_at (Evoral::Beats const & b) const;
317         Meter const & meter_at (Timecode::BBT_Time const & bbt) const;
318         Tempo const & tempo_at (superclock_t sc) const;
319         Tempo const & tempo_at (Evoral::Beats const &b) const;
320         Tempo const & tempo_at (Timecode::BBT_Time const & bbt) const;
321
322         Timecode::BBT_Time bbt_at (superclock_t sc) const;
323         Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
324         Evoral::Beats quarter_note_at (superclock_t sc) const;
325         Evoral::Beats quarter_note_at (Timecode::BBT_Time const &) const;
326         superclock_t superclock_at (Evoral::Beats const &) const;
327         superclock_t superclock_at (Timecode::BBT_Time const &) const;
328
329         TempoMapPoint const & const_point_at (superclock_t sc) const { return *const_iterator_at (sc); }
330         TempoMapPoint const & const_point_at (Evoral::Beats const & b) const { return *const_iterator_at (b); }
331         TempoMapPoint const & const_point_at (Timecode::BBT_Time const & bbt) const { return *const_iterator_at (bbt); }
332
333         TempoMapPoint const & const_point_after (superclock_t sc) const;
334         TempoMapPoint const & const_point_after (Evoral::Beats const & b) const;
335         TempoMapPoint const & const_point_after (Timecode::BBT_Time const & bbt) const;
336
337         void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end);
338
339         struct EmptyTempoMapException : public std::exception {
340                 virtual const char* what() const throw() { return "TempoMap is empty"; }
341         };
342
343         void dump (std::ostream&);
344         void rebuild (superclock_t limit);
345
346    private:
347         TempoMapPoints _points;
348         framecnt_t     _sample_rate;
349         mutable Glib::Threads::RWLock _lock;
350
351         /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
352          *
353          * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
354          *
355          * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
356          *
357          *    - if the map is empty, an exception is thrown
358          *    - if the given time is before the first map entry, _points.begin() is returned
359          *    - if the given time is after the last map entry, the equivalent of _points.rbegin() is returned
360          *    - if the given time is within the map entries, a valid iterator will be returned
361          */
362
363         TempoMapPoints::iterator iterator_at (superclock_t sc);
364         TempoMapPoints::iterator iterator_at (Evoral::Beats const &);
365         TempoMapPoints::iterator iterator_at (Timecode::BBT_Time const &);
366
367         TempoMapPoints::const_iterator const_iterator_at (superclock_t sc) const { return const_cast<TempoMap*>(this)->iterator_at (sc); }
368         TempoMapPoints::const_iterator const_iterator_at (Evoral::Beats const & b) const { return const_cast<TempoMap*>(this)->iterator_at (b); }
369         TempoMapPoints::const_iterator const_iterator_at (Timecode::BBT_Time const & bbt) const { return const_cast<TempoMap*>(this)->iterator_at (bbt); }
370
371         /* Returns the TempoMapPoint at or most immediately preceding the given time. If the given time is
372          * before the first map entry, then the first map entry will be returned, which underlies the semantics
373          * that the first map entry's values propagate backwards in time if not at absolute zero.
374          *
375          * As for iterator_at(), define both const+const and non-const variants, because C++ won't let us return a non-const iterator
376            from a const method (which is a bit silly, but presumably aids compiler reasoning).
377         */
378
379         TempoMapPoint & point_at (superclock_t sc) { return *iterator_at (sc); }
380         TempoMapPoint & point_at (Evoral::Beats const & b) { return *iterator_at (b); }
381         TempoMapPoint & point_at (Timecode::BBT_Time const & bbt) { return *iterator_at (bbt); }
382
383         Meter const & meter_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
384         Meter const & meter_at_locked (Evoral::Beats const & b) const { return const_point_at (b).metric(); }
385         Meter const & meter_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
386         Tempo const & tempo_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
387         Tempo const & tempo_at_locked (Evoral::Beats const &b) const { return const_point_at (b).metric(); }
388         Tempo const & tempo_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
389         Timecode::BBT_Time bbt_at_locked (superclock_t sc) const;
390         Timecode::BBT_Time bbt_at_locked (Evoral::Beats const &) const;
391         Evoral::Beats quarter_note_at_locked (superclock_t sc) const;
392         Evoral::Beats quarter_note_at_locked (Timecode::BBT_Time const &) const;
393         superclock_t superclock_at_locked (Evoral::Beats const &) const;
394         superclock_t superclock_at_locked (Timecode::BBT_Time const &) const;
395
396         void rebuild_locked (superclock_t limit);
397         void dump_locked (std::ostream&);
398 };
399
400 }
401
402 std::ostream& operator<<(std::ostream&, ARDOUR::TempoMapPoint const &);
403 std::ostream& operator<<(std::ostream&, ARDOUR::Tempo const &);
404 std::ostream& operator<<(std::ostream&, ARDOUR::Meter const &);
405
406 #endif /* __ardour_tempo_h__ */