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 Flag flags() const { return _flags; }
200 bool is_explicit() const { return _flags != Flag (0); }
201 bool is_implicit() const { return _flags == Flag (0); }
203 superclock_t superclocks_per_note_type (int8_t note_type) const {
205 return _explicit.metric.superclocks_per_note_type (note_type);
207 return _reference->superclocks_per_note_type (note_type);
210 struct BadTempoMetricLookup : public std::exception {
211 virtual const char* what() const throw() { return "cannot obtain non-const Metric from implicit map point"; }
214 bool dirty() const { return _dirty; }
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(); }
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); } }
226 /* None of these properties can be set for an Implicit point, because
227 * they are determined by the TempoMapPoint pointed to by _reference.
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; } }
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.
242 TempoMetric tm (_explicit.metric);
243 _explicit.metric = tm;
247 void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
249 Evoral::Beats quarters_at (superclock_t sc) const;
250 Evoral::Beats quarters_at (Timecode::BBT_Time const &) const;
252 Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
255 XMLNode& get_state() const;
256 int set_state (XMLNode const&, int version);
259 struct SuperClockComparator {
260 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
263 struct QuarterComparator {
264 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
267 struct BBTComparator {
268 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
272 friend class TempoMap;
273 void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
276 struct ExplicitInfo {
277 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
280 PositionLockStyle lock_style;
285 TempoMapPoint const * _reference;
286 ExplicitInfo _explicit;
288 superclock_t _sclock;
289 Evoral::Beats _quarters;
290 Timecode::BBT_Time _bbt;
294 typedef std::list<TempoMapPoint> TempoMapPoints;
296 class LIBARDOUR_API TempoMap
299 TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr);
301 void set_sample_rate (framecnt_t sr);
302 framecnt_t sample_rate() const { return _sample_rate; }
304 void remove_explicit_point (superclock_t);
306 bool move_to (superclock_t current, superclock_t destination, bool push = false);
308 bool set_tempo_and_meter (Tempo const &, Meter const &, superclock_t, bool ramp, bool flexible);
310 bool set_tempo (Tempo const &, Timecode::BBT_Time const &, bool ramp = false);
311 bool set_tempo (Tempo const &, superclock_t, bool ramp = false);
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 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); }
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;
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
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
348 void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end, Evoral::Beats const & resolution);
350 void get_bar_grid (TempoMapPoints& points, superclock_t start, superclock_t end, int32_t bar_gap);
352 struct EmptyTempoMapException : public std::exception {
353 virtual const char* what() const throw() { return "TempoMap is empty"; }
356 void dump (std::ostream&);
357 void rebuild (superclock_t limit);
360 TempoMapPoints _points;
361 framecnt_t _sample_rate;
362 mutable Glib::Threads::RWLock _lock;
364 /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
366 * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
368 * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
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
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 &);
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); }
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.
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).
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); }
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;
409 void rebuild_locked (superclock_t limit);
410 void dump_locked (std::ostream&);
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 &);
419 #endif /* __ardour_tempo_h__ */