1 #ifndef __ardour_tempo_h__
2 #define __ardour_tempo_h__
10 #include <glibmm/threads.h>
12 #include "evoral/Beats.hpp"
14 #include "ardour/ardour.h"
15 #include "ardour/superclock.h"
17 #include "timecode/bbt_time.h"
24 /** Tempo, the speed at which musical time progresses (BPM).
27 class LIBARDOUR_API Tempo {
30 * @param npm Note Types per minute
31 * @param type Note Type (default `4': quarter note)
33 Tempo (double npm, int type = 4) : _superclocks_per_note_type (double_npm_to_sc (npm)), _note_type (type) {}
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)
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); }
41 int note_type () const { return _note_type; }
43 superclock_t superclocks_per_note_type () const {
44 return _superclocks_per_note_type;
46 superclock_t superclocks_per_note_type (int note_type) const {
47 return (_superclocks_per_note_type * _note_type) / note_type;
49 superclock_t superclocks_per_quarter_note () const {
50 return superclocks_per_note_type (4);
53 Tempo& operator=(Tempo const& other) {
55 _superclocks_per_note_type = other._superclocks_per_note_type;
56 _note_type = other._note_type;
62 superclock_t _superclocks_per_note_type;
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); }
69 /** Meter, or time signature (subdivisions per bar, and which note type is a single subdivision). */
70 class LIBARDOUR_API Meter {
72 Meter (int8_t dpb, int8_t nv) : _note_value (nv), _divisions_per_bar (dpb) {}
74 int divisions_per_bar () const { return _divisions_per_bar; }
75 int note_value() const { return _note_value; }
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(); }
80 Meter& operator=(Meter const & other) {
82 _divisions_per_bar = other._divisions_per_bar;
83 _note_value = other._note_value;
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;
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;
96 Evoral::Beats to_quarters (Timecode::BBT_Offset const &) const;
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.
103 /* how many of '_note_value' make up a bar or measure */
104 int8_t _divisions_per_bar;
107 /** Helper class to keep track of the Meter *AND* Tempo in effect
108 at a given point in time.
110 class LIBARDOUR_API TempoMetric : public Tempo, public Meter {
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) {}
115 double c_per_superclock () const { return _c_per_superclock; }
116 double c_per_quarter () const { return _c_per_quarter; }
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);
121 superclock_t superclocks_per_bar (framecnt_t sr) const;
122 superclock_t superclocks_per_grid (framecnt_t sr) const;
124 superclock_t superclock_at_qn (Evoral::Beats const & qn) const;
125 superclock_t superclock_per_note_type_at_superclock (superclock_t) const;
127 bool ramped () const { return _ramped; }
128 void set_ramped (bool yn) { _ramped = yn; } /* caller must mark something dirty to force recompute */
131 double _c_per_quarter;
132 double _c_per_superclock;
136 /** Tempo Map - mapping of timecode to musical time.
137 * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo
142 we have several different ways of talking about time:
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
149 * QUARTER NOTES : just what the name says. A lot of MIDI software and
150 concepts assume that a "beat" is a quarter-note.
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).
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.
165 * MINUTES : wallclock time measurement. related to SAMPLES or SUPERCLOCK
166 only when a sample rate is known.
169 * SAMPLES : audio time measurement. Related to MINUTES or SUPERCLOCK only
170 when a sample rate is known
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.
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
185 class LIBARDOUR_API TempoMapPoint
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) {}
199 bool is_explicit() const { return _flags != Flag (0); }
200 bool is_implicit() const { return _flags == Flag (0); }
202 superclock_t superclocks_per_note_type (int8_t note_type) const {
204 return _explicit.metric.superclocks_per_note_type (note_type);
206 return _reference->superclocks_per_note_type (note_type);
209 struct BadTempoMetricLookup : public std::exception {
210 virtual const char* what() const throw() { return "cannot obtain non-const Metric from implicit map point"; }
213 bool dirty() const { return _dirty; }
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(); }
224 /* None of these properties can be set for an Implicit point, because
225 * they are determined by the TempoMapPoint pointed to by _reference.
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; } }
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.
240 TempoMetric tm (_explicit.metric);
241 _explicit.metric = tm;
245 void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
247 Evoral::Beats quarters_at (superclock_t sc) const;
248 Evoral::Beats quarters_at (Timecode::BBT_Time const &) const;
250 Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
253 XMLNode& get_state() const;
254 int set_state (XMLNode const&, int version);
257 struct SuperClockComparator {
258 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
261 struct QuarterComparator {
262 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
265 struct BBTComparator {
266 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
270 friend class TempoMap;
271 void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
274 struct ExplicitInfo {
275 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
278 PositionLockStyle lock_style;
283 TempoMapPoint const * _reference;
284 ExplicitInfo _explicit;
286 superclock_t _sclock;
287 Evoral::Beats _quarters;
288 Timecode::BBT_Time _bbt;
292 typedef std::list<TempoMapPoint> TempoMapPoints;
294 class LIBARDOUR_API TempoMap
297 TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr);
299 void set_sample_rate (framecnt_t sr);
300 framecnt_t sample_rate() const { return _sample_rate; }
302 void remove_explicit_point (superclock_t);
304 void move_implicit (superclock_t current, superclock_t destination);
305 void move_explicit (superclock_t current, superclock_t destination);
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);
311 //bool set_meter_at (Meter const &, Evoral::Beats const &);
313 bool set_meter (Meter const &, Timecode::BBT_Time const &);
314 bool set_meter (Meter const &, superclock_t);
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;
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;
330 struct EmptyTempoMapException : public std::exception {
331 virtual const char* what() const throw() { return "TempoMap is empty"; }
334 void dump (std::ostream&);
335 void rebuild (superclock_t limit);
338 TempoMapPoints _points;
339 framecnt_t _sample_rate;
340 mutable Glib::Threads::RWLock _lock;
342 /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
344 * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
346 * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
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
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 &);
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); }
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.
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).
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); }
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); }
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;
391 void move_explicit_to (TempoMapPoints::iterator, superclock_t destination);
393 void rebuild_locked (superclock_t limit);
394 void dump_locked (std::ostream&);
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 &);
403 #endif /* __ardour_tempo_h__ */