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