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 PositionLockStyle lock_style() const { return is_explicit() ? _explicit.lock_style : _reference->lock_style(); }
222 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); } }
223 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 /* None of these properties can be set for an Implicit point, because
226 * they are determined by the TempoMapPoint pointed to by _reference.
229 void set_sclock (superclock_t sc) { if (is_explicit()) { _sclock = sc; _dirty = true; } }
230 void set_quarters (Evoral::Beats const & q) { if (is_explicit()) { _quarters = q; _dirty = true; } }
231 void set_bbt (Timecode::BBT_Time const & bbt) { if (is_explicit()) { _bbt = bbt; _dirty = true; } }
232 void set_dirty (bool yn) { if (is_explicit()) { _dirty = yn; } }
233 void set_lock_style (PositionLockStyle psl) { if (is_explicit()) { _explicit.lock_style = psl; _dirty = true; } }
235 void make_explicit (Flag f) {
236 _flags = Flag (_flags|f);
237 /* since _metric and _reference are part of an anonymous union,
238 avoid possible compiler glitches by copying to a stack
239 variable first, then assign.
241 TempoMetric tm (_explicit.metric);
242 _explicit.metric = tm;
246 void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
248 Evoral::Beats quarters_at (superclock_t sc) const;
249 Evoral::Beats quarters_at (Timecode::BBT_Time const &) const;
251 Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
254 XMLNode& get_state() const;
255 int set_state (XMLNode const&, int version);
258 struct SuperClockComparator {
259 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
262 struct QuarterComparator {
263 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
266 struct BBTComparator {
267 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
271 friend class TempoMap;
272 void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
275 struct ExplicitInfo {
276 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
279 PositionLockStyle lock_style;
284 TempoMapPoint const * _reference;
285 ExplicitInfo _explicit;
287 superclock_t _sclock;
288 Evoral::Beats _quarters;
289 Timecode::BBT_Time _bbt;
293 typedef std::list<TempoMapPoint> TempoMapPoints;
295 class LIBARDOUR_API TempoMap
298 TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr);
300 void set_sample_rate (framecnt_t sr);
301 framecnt_t sample_rate() const { return _sample_rate; }
303 void remove_explicit_point (superclock_t);
305 bool move_to (superclock_t current, superclock_t destination, bool push = false);
307 bool set_tempo_and_meter (Tempo const &, Meter const &, superclock_t, bool ramp, bool flexible);
309 bool set_tempo (Tempo const &, Timecode::BBT_Time const &, bool ramp = false);
310 bool set_tempo (Tempo const &, superclock_t, bool ramp = false);
312 bool set_meter (Meter const &, Timecode::BBT_Time const &);
313 bool set_meter (Meter const &, superclock_t);
315 Meter const & meter_at (superclock_t sc) const;
316 Meter const & meter_at (Evoral::Beats const & b) const;
317 Meter const & meter_at (Timecode::BBT_Time const & bbt) const;
318 Tempo const & tempo_at (superclock_t sc) const;
319 Tempo const & tempo_at (Evoral::Beats const &b) const;
320 Tempo const & tempo_at (Timecode::BBT_Time const & bbt) const;
322 Timecode::BBT_Time bbt_at (superclock_t sc) const;
323 Timecode::BBT_Time bbt_at (Evoral::Beats const &) const;
324 Evoral::Beats quarter_note_at (superclock_t sc) const;
325 Evoral::Beats quarter_note_at (Timecode::BBT_Time const &) const;
326 superclock_t superclock_at (Evoral::Beats const &) const;
327 superclock_t superclock_at (Timecode::BBT_Time const &) const;
329 TempoMapPoint const & const_point_at (superclock_t sc) const { return *const_iterator_at (sc); }
330 TempoMapPoint const & const_point_at (Evoral::Beats const & b) const { return *const_iterator_at (b); }
331 TempoMapPoint const & const_point_at (Timecode::BBT_Time const & bbt) const { return *const_iterator_at (bbt); }
333 TempoMapPoint const & const_point_after (superclock_t sc) const;
334 TempoMapPoint const & const_point_after (Evoral::Beats const & b) const;
335 TempoMapPoint const & const_point_after (Timecode::BBT_Time const & bbt) const;
337 void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end);
339 struct EmptyTempoMapException : public std::exception {
340 virtual const char* what() const throw() { return "TempoMap is empty"; }
343 void dump (std::ostream&);
344 void rebuild (superclock_t limit);
347 TempoMapPoints _points;
348 framecnt_t _sample_rate;
349 mutable Glib::Threads::RWLock _lock;
351 /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
353 * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
355 * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
357 * - if the map is empty, an exception is thrown
358 * - if the given time is before the first map entry, _points.begin() is returned
359 * - if the given time is after the last map entry, the equivalent of _points.rbegin() is returned
360 * - if the given time is within the map entries, a valid iterator will be returned
363 TempoMapPoints::iterator iterator_at (superclock_t sc);
364 TempoMapPoints::iterator iterator_at (Evoral::Beats const &);
365 TempoMapPoints::iterator iterator_at (Timecode::BBT_Time const &);
367 TempoMapPoints::const_iterator const_iterator_at (superclock_t sc) const { return const_cast<TempoMap*>(this)->iterator_at (sc); }
368 TempoMapPoints::const_iterator const_iterator_at (Evoral::Beats const & b) const { return const_cast<TempoMap*>(this)->iterator_at (b); }
369 TempoMapPoints::const_iterator const_iterator_at (Timecode::BBT_Time const & bbt) const { return const_cast<TempoMap*>(this)->iterator_at (bbt); }
371 /* Returns the TempoMapPoint at or most immediately preceding the given time. If the given time is
372 * before the first map entry, then the first map entry will be returned, which underlies the semantics
373 * that the first map entry's values propagate backwards in time if not at absolute zero.
375 * As for iterator_at(), define both const+const and non-const variants, because C++ won't let us return a non-const iterator
376 from a const method (which is a bit silly, but presumably aids compiler reasoning).
379 TempoMapPoint & point_at (superclock_t sc) { return *iterator_at (sc); }
380 TempoMapPoint & point_at (Evoral::Beats const & b) { return *iterator_at (b); }
381 TempoMapPoint & point_at (Timecode::BBT_Time const & bbt) { return *iterator_at (bbt); }
383 Meter const & meter_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
384 Meter const & meter_at_locked (Evoral::Beats const & b) const { return const_point_at (b).metric(); }
385 Meter const & meter_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
386 Tempo const & tempo_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
387 Tempo const & tempo_at_locked (Evoral::Beats const &b) const { return const_point_at (b).metric(); }
388 Tempo const & tempo_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
389 Timecode::BBT_Time bbt_at_locked (superclock_t sc) const;
390 Timecode::BBT_Time bbt_at_locked (Evoral::Beats const &) const;
391 Evoral::Beats quarter_note_at_locked (superclock_t sc) const;
392 Evoral::Beats quarter_note_at_locked (Timecode::BBT_Time const &) const;
393 superclock_t superclock_at_locked (Evoral::Beats const &) const;
394 superclock_t superclock_at_locked (Timecode::BBT_Time const &) const;
396 void rebuild_locked (superclock_t limit);
397 void dump_locked (std::ostream&);
402 std::ostream& operator<<(std::ostream&, ARDOUR::TempoMapPoint const &);
403 std::ostream& operator<<(std::ostream&, ARDOUR::Tempo const &);
404 std::ostream& operator<<(std::ostream&, ARDOUR::Meter const &);
406 #endif /* __ardour_tempo_h__ */