more changes to broken-out tempo code
[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         Flag flags() const       { return _flags; }
200         bool is_explicit() const { return _flags != Flag (0); }
201         bool is_implicit() const { return _flags == Flag (0); }
202
203         superclock_t superclocks_per_note_type (int8_t note_type) const {
204                 if (is_explicit()) {
205                         return _explicit.metric.superclocks_per_note_type (note_type);
206                 }
207                 return _reference->superclocks_per_note_type (note_type);
208         }
209
210         struct BadTempoMetricLookup : public std::exception {
211                 virtual const char* what() const throw() { return "cannot obtain non-const Metric from implicit map point"; }
212         };
213
214         bool                dirty()  const { return _dirty; }
215
216         superclock_t        sclock() const      { return _sclock; }
217         Evoral::Beats const & quarters() const  { return _quarters; }
218         Timecode::BBT_Time  const & bbt() const { return _bbt; }
219         bool                ramped() const      { return metric().ramped(); }
220         TempoMetric const & metric() const      { return is_explicit() ? _explicit.metric : _reference->metric(); }
221         PositionLockStyle   lock_style() const  { return is_explicit() ? _explicit.lock_style : _reference->lock_style(); }
222
223         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); } }
224         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); } }
225
226         /* None of these properties can be set for an Implicit point, because
227          * they are determined by the TempoMapPoint pointed to by _reference.
228          */
229
230         void set_sclock (superclock_t  sc) { if (is_explicit()) { _sclock = sc; _dirty = true; } }
231         void set_quarters (Evoral::Beats const & q) { if (is_explicit()) { _quarters = q; _dirty = true;  } }
232         void set_bbt (Timecode::BBT_Time const & bbt) {  if (is_explicit()) { _bbt = bbt; _dirty = true;  } }
233         void set_dirty (bool yn) { if (is_explicit()) { _dirty = yn; } }
234         void set_lock_style (PositionLockStyle psl) {  if (is_explicit()) { _explicit.lock_style = psl; _dirty = true; } }
235
236         void make_explicit (Flag f) {
237                 _flags = Flag (_flags|f);
238                 /* since _metric and _reference are part of an anonymous union,
239                    avoid possible compiler glitches by copying to a stack
240                    variable first, then assign.
241                 */
242                 TempoMetric tm (_explicit.metric);
243                 _explicit.metric = tm;
244                 _dirty = true;
245         }
246
247         void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
248
249         Evoral::Beats quarters_at (superclock_t sc) const;
250         Evoral::Beats quarters_at (Timecode::BBT_Time const &) const;
251
252         Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
253
254 #if 0
255         XMLNode& get_state() const;
256         int set_state (XMLNode const&, int version);
257 #endif
258
259         struct SuperClockComparator {
260                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
261         };
262
263         struct QuarterComparator {
264                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
265         };
266
267         struct BBTComparator {
268                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
269         };
270
271   protected:
272         friend class TempoMap;
273         void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
274
275   private:
276         struct ExplicitInfo {
277                 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
278
279                 TempoMetric       metric;
280                 PositionLockStyle lock_style;
281         };
282
283         Flag                  _flags;
284         union {
285                 TempoMapPoint const * _reference;
286                 ExplicitInfo          _explicit;
287         };
288         superclock_t          _sclock;
289         Evoral::Beats         _quarters;
290         Timecode::BBT_Time    _bbt;
291         bool                  _dirty;
292 };
293
294 typedef std::list<TempoMapPoint> TempoMapPoints;
295
296 class LIBARDOUR_API TempoMap
297 {
298    public:
299         TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr);
300
301         void set_sample_rate (framecnt_t sr);
302         framecnt_t sample_rate() const { return _sample_rate; }
303
304         void remove_explicit_point (superclock_t);
305
306         bool move_to (superclock_t current, superclock_t destination, bool push = false);
307
308         bool set_tempo_and_meter (Tempo const &, Meter const &, superclock_t, bool ramp, bool flexible);
309
310         bool set_tempo (Tempo const &, Timecode::BBT_Time const &, bool ramp = false);
311         bool set_tempo (Tempo const &, superclock_t, bool ramp = false);
312
313         bool set_meter (Meter const &, Timecode::BBT_Time const &);
314         bool set_meter (Meter const &, superclock_t);
315
316         Meter const & meter_at (superclock_t sc) const;
317         Meter const & meter_at (Evoral::Beats const & b) const;
318         Meter const & meter_at (Timecode::BBT_Time const & bbt) const;
319         Tempo const & tempo_at (superclock_t sc) const;
320         Tempo const & tempo_at (Evoral::Beats const &b) const;
321         Tempo const & tempo_at (Timecode::BBT_Time const & bbt) const;
322
323         Timecode::BBT_Time bbt_at (superclock_t sc) const;
324         Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
325         Evoral::Beats quarter_note_at (superclock_t sc) const;
326         Evoral::Beats quarter_note_at (Timecode::BBT_Time const &) const;
327         superclock_t superclock_at (Evoral::Beats const &) const;
328         superclock_t superclock_at (Timecode::BBT_Time const &) const;
329
330         TempoMapPoint const & const_point_at (superclock_t sc) const { return *const_iterator_at (sc); }
331         TempoMapPoint const & const_point_at (Evoral::Beats const & b) const { return *const_iterator_at (b); }
332         TempoMapPoint const & const_point_at (Timecode::BBT_Time const & bbt) const { return *const_iterator_at (bbt); }
333
334         TempoMapPoint const & const_point_after (superclock_t sc) const;
335         TempoMapPoint const & const_point_after (Evoral::Beats const & b) const;
336         TempoMapPoint const & const_point_after (Timecode::BBT_Time const & bbt) const;
337
338         /* If resolution == Evoral::Beats() (i.e. zero), then the grid that is
339            returned will contain a mixture of implicit and explicit points,
340            and will only be valid as long as this map remains unchanged
341            (because the implicit points may reference explicit points in the
342            map.
343
344            If resolution != Evoral::Beats() (i.e. non-zero), then the in-out @param
345            grid will contain only explicit points that do not reference this
346            map in anyway.
347         */
348         void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end, Evoral::Beats const & resolution);
349
350         void get_bar_grid (TempoMapPoints& points, superclock_t start, superclock_t end, int32_t bar_gap);
351
352         struct EmptyTempoMapException : public std::exception {
353                 virtual const char* what() const throw() { return "TempoMap is empty"; }
354         };
355
356         void dump (std::ostream&);
357         void rebuild (superclock_t limit);
358
359    private:
360         TempoMapPoints _points;
361         framecnt_t     _sample_rate;
362         mutable Glib::Threads::RWLock _lock;
363
364         /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
365          *
366          * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
367          *
368          * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
369          *
370          *    - if the map is empty, an exception is thrown
371          *    - if the given time is before the first map entry, _points.begin() is returned
372          *    - if the given time is after the last map entry, the equivalent of _points.rbegin() is returned
373          *    - if the given time is within the map entries, a valid iterator will be returned
374          */
375
376         TempoMapPoints::iterator iterator_at (superclock_t sc);
377         TempoMapPoints::iterator iterator_at (Evoral::Beats const &);
378         TempoMapPoints::iterator iterator_at (Timecode::BBT_Time const &);
379
380         TempoMapPoints::const_iterator const_iterator_at (superclock_t sc) const { return const_cast<TempoMap*>(this)->iterator_at (sc); }
381         TempoMapPoints::const_iterator const_iterator_at (Evoral::Beats const & b) const { return const_cast<TempoMap*>(this)->iterator_at (b); }
382         TempoMapPoints::const_iterator const_iterator_at (Timecode::BBT_Time const & bbt) const { return const_cast<TempoMap*>(this)->iterator_at (bbt); }
383
384         /* Returns the TempoMapPoint at or most immediately preceding the given time. If the given time is
385          * before the first map entry, then the first map entry will be returned, which underlies the semantics
386          * that the first map entry's values propagate backwards in time if not at absolute zero.
387          *
388          * As for iterator_at(), define both const+const and non-const variants, because C++ won't let us return a non-const iterator
389            from a const method (which is a bit silly, but presumably aids compiler reasoning).
390         */
391
392         TempoMapPoint & point_at (superclock_t sc) { return *iterator_at (sc); }
393         TempoMapPoint & point_at (Evoral::Beats const & b) { return *iterator_at (b); }
394         TempoMapPoint & point_at (Timecode::BBT_Time const & bbt) { return *iterator_at (bbt); }
395
396         Meter const & meter_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
397         Meter const & meter_at_locked (Evoral::Beats const & b) const { return const_point_at (b).metric(); }
398         Meter const & meter_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
399         Tempo const & tempo_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
400         Tempo const & tempo_at_locked (Evoral::Beats const &b) const { return const_point_at (b).metric(); }
401         Tempo const & tempo_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
402         Timecode::BBT_Time bbt_at_locked (superclock_t sc) const;
403         Timecode::BBT_Time bbt_at_locked (Evoral::Beats const &) const;
404         Evoral::Beats quarter_note_at_locked (superclock_t sc) const;
405         Evoral::Beats quarter_note_at_locked (Timecode::BBT_Time const &) const;
406         superclock_t superclock_at_locked (Evoral::Beats const &) const;
407         superclock_t superclock_at_locked (Timecode::BBT_Time const &) const;
408
409         void rebuild_locked (superclock_t limit);
410         void dump_locked (std::ostream&);
411 };
412
413 }
414
415 std::ostream& operator<<(std::ostream&, ARDOUR::TempoMapPoint const &);
416 std::ostream& operator<<(std::ostream&, ARDOUR::Tempo const &);
417 std::ostream& operator<<(std::ostream&, ARDOUR::Meter const &);
418
419 #endif /* __ardour_tempo_h__ */