db3cb4495467736fc18c8f38a82e4561386cab5a
[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         /* Implicit points are not allowed to return non-const references to their reference metric */
221         TempoMetric & metric()                  { if (is_explicit()) { return _explicit.metric; } throw BadTempoMetricLookup(); }
222         PositionLockStyle   lock_style() const  { return is_explicit() ? _explicit.lock_style : _reference->lock_style(); }
223
224         /* None of these properties can be set for an Implicit point, because
225          * they are determined by the TempoMapPoint pointed to by _reference.
226          */
227
228         void set_sclock (superclock_t  sc) { if (is_explicit()) { _sclock = sc; _dirty = true; } }
229         void set_quarters (Evoral::Beats const & q) { if (is_explicit()) { _quarters = q; _dirty = true;  } }
230         void set_bbt (Timecode::BBT_Time const & bbt) {  if (is_explicit()) { _bbt = bbt; _dirty = true;  } }
231         void set_dirty (bool yn) { if (is_explicit()) { _dirty = yn; } }
232         void set_lock_style (PositionLockStyle psl) {  if (is_explicit()) { _explicit.lock_style = psl; _dirty = true; } }
233
234         void make_explicit (Flag f) {
235                 _flags = Flag (_flags|f);
236                 /* since _metric and _reference are part of an anonymous union,
237                    avoid possible compiler glitches by copying to a stack
238                    variable first, then assign.
239                 */
240                 TempoMetric tm (_explicit.metric);
241                 _explicit.metric = tm;
242                 _dirty = true;
243         }
244
245         void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
246
247         Evoral::Beats quarters_at (superclock_t sc) const;
248         Evoral::Beats quarters_at (Timecode::BBT_Time const &) const;
249
250         Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
251
252 #if 0
253         XMLNode& get_state() const;
254         int set_state (XMLNode const&, int version);
255 #endif
256
257         struct SuperClockComparator {
258                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
259         };
260
261         struct QuarterComparator {
262                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
263         };
264
265         struct BBTComparator {
266                 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
267         };
268
269   protected:
270         friend class TempoMap;
271         void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
272
273   private:
274         struct ExplicitInfo {
275                 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
276
277                 TempoMetric       metric;
278                 PositionLockStyle lock_style;
279         };
280
281         Flag                  _flags;
282         union {
283                 TempoMapPoint const * _reference;
284                 ExplicitInfo          _explicit;
285         };
286         superclock_t          _sclock;
287         Evoral::Beats         _quarters;
288         Timecode::BBT_Time    _bbt;
289         bool                  _dirty;
290 };
291
292 typedef std::list<TempoMapPoint> TempoMapPoints;
293
294 class LIBARDOUR_API TempoMap
295 {
296    public:
297         TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr);
298
299         void set_sample_rate (framecnt_t sr);
300         framecnt_t sample_rate() const { return _sample_rate; }
301
302         void remove_explicit_point (superclock_t);
303
304         void move_implicit (superclock_t current, superclock_t destination);
305         void move_explicit (superclock_t current, superclock_t destination);
306
307         //bool set_tempo_at (Tempo const &, Evoral::Beats const &, PositionLockStyle psl, bool ramp = false);
308         bool set_tempo (Tempo const &, Timecode::BBT_Time const &, bool ramp = false);
309         bool set_tempo (Tempo const &, superclock_t, bool ramp = false);
310
311         //bool set_meter_at (Meter const &, Evoral::Beats const &);
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         struct EmptyTempoMapException : public std::exception {
331                 virtual const char* what() const throw() { return "TempoMap is empty"; }
332         };
333
334         void dump (std::ostream&);
335         void rebuild (superclock_t limit);
336
337    private:
338         TempoMapPoints _points;
339         framecnt_t     _sample_rate;
340         mutable Glib::Threads::RWLock _lock;
341
342         /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
343          *
344          * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
345          *
346          * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
347          *
348          *    - if the map is empty, an exception is thrown
349          *    - if the given time is before the first map entry, _points.begin() is returned
350          *    - if the given time is after the last map entry, the equivalent of _points.rbegin() is returned
351          *    - if the given time is within the map entries, a valid iterator will be returned
352          */
353
354         TempoMapPoints::iterator iterator_at (superclock_t sc);
355         TempoMapPoints::iterator iterator_at (Evoral::Beats const &);
356         TempoMapPoints::iterator iterator_at (Timecode::BBT_Time const &);
357
358         TempoMapPoints::const_iterator const_iterator_at (superclock_t sc) const { return const_cast<TempoMap*>(this)->iterator_at (sc); }
359         TempoMapPoints::const_iterator const_iterator_at (Evoral::Beats const & b) const { return const_cast<TempoMap*>(this)->iterator_at (b); }
360         TempoMapPoints::const_iterator const_iterator_at (Timecode::BBT_Time const & bbt) const { return const_cast<TempoMap*>(this)->iterator_at (bbt); }
361
362         /* Returns the TempoMapPoint at or most immediately preceding the given time. If the given time is
363          * before the first map entry, then the first map entry will be returned, which underlies the semantics
364          * that the first map entry's values propagate backwards in time if not at absolute zero.
365          *
366          * As for iterator_at(), define both const+const and non-const variants, because C++ won't let us return a non-const iterator
367            from a const method (which is a bit silly, but presumably aids compiler reasoning).
368         */
369
370         TempoMapPoint & point_at (superclock_t sc) { return *iterator_at (sc); }
371         TempoMapPoint & point_at (Evoral::Beats const & b) { return *iterator_at (b); }
372         TempoMapPoint & point_at (Timecode::BBT_Time const & bbt) { return *iterator_at (bbt); }
373
374         TempoMapPoint const & const_point_at (superclock_t sc) const { return *const_iterator_at (sc); }
375         TempoMapPoint const & const_point_at (Evoral::Beats const & b) const { return *const_iterator_at (b); }
376         TempoMapPoint const & const_point_at (Timecode::BBT_Time const & bbt) const { return *const_iterator_at (bbt); }
377
378         Meter const & meter_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
379         Meter const & meter_at_locked (Evoral::Beats const & b) const { return const_point_at (b).metric(); }
380         Meter const & meter_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
381         Tempo const & tempo_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
382         Tempo const & tempo_at_locked (Evoral::Beats const &b) const { return const_point_at (b).metric(); }
383         Tempo const & tempo_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
384         Timecode::BBT_Time bbt_at_locked (superclock_t sc) const;
385         Timecode::BBT_Time bbt_at_locked (Evoral::Beats const &) const;
386         Evoral::Beats quarter_note_at_locked (superclock_t sc) const;
387         Evoral::Beats quarter_note_at_locked (Timecode::BBT_Time const &) const;
388         superclock_t superclock_at_locked (Evoral::Beats const &) const;
389         superclock_t superclock_at_locked (Timecode::BBT_Time const &) const;
390
391         void move_explicit_to (TempoMapPoints::iterator, superclock_t destination);
392
393         void rebuild_locked (superclock_t limit);
394         void dump_locked (std::ostream&);
395 };
396
397 }
398
399 std::ostream& operator<<(std::ostream&, ARDOUR::TempoMapPoint const &);
400 std::ostream& operator<<(std::ostream&, ARDOUR::Tempo const &);
401 std::ostream& operator<<(std::ostream&, ARDOUR::Meter const &);
402
403 #endif /* __ardour_tempo_h__ */