1 #ifndef __ardour_tempo_h__
2 #define __ardour_tempo_h__
10 #include <glibmm/threads.h>
12 #include "pbd/signals.h"
14 #include "temporal/beats.h"
16 #include "ardour/ardour.h"
17 #include "ardour/superclock.h"
19 #include "temporal/bbt_time.h"
26 /** Tempo, the speed at which musical time progresses (BPM).
29 class LIBARDOUR_API Tempo {
32 * @param npm Note Types per minute
33 * @param type Note Type (default `4': quarter note)
35 Tempo (double npm, int type = 4) : _superclocks_per_note_type (double_npm_to_sc (npm)), _note_type (type) {}
37 /* these two methods should only be used to show and collect information to the user (for whom
38 * bpm as a floating point number is the obvious representation)
40 double note_types_per_minute () const { return (superclock_ticks_per_second * 60.0) / _superclocks_per_note_type; }
41 void set_note_types_per_minute (double npm) { _superclocks_per_note_type = double_npm_to_sc (npm); }
43 int note_type () const { return _note_type; }
45 superclock_t superclocks_per_note_type () const {
46 return _superclocks_per_note_type;
48 superclock_t superclocks_per_note_type (int note_type) const {
49 return (_superclocks_per_note_type * _note_type) / note_type;
51 superclock_t superclocks_per_quarter_note () const {
52 return superclocks_per_note_type (4);
55 Tempo& operator=(Tempo const& other) {
57 _superclocks_per_note_type = other._superclocks_per_note_type;
58 _note_type = other._note_type;
64 superclock_t _superclocks_per_note_type;
67 static inline double sc_to_double_npm (superclock_t sc) { return (superclock_ticks_per_second * 60.0) / sc; }
68 static inline superclock_t double_npm_to_sc (double npm) { return llrint ((superclock_ticks_per_second / npm) * 60.0); }
71 /** Meter, or time signature (subdivisions per bar, and which note type is a single subdivision). */
72 class LIBARDOUR_API Meter {
74 Meter (int8_t dpb, int8_t nv) : _note_value (nv), _divisions_per_bar (dpb) {}
76 int divisions_per_bar () const { return _divisions_per_bar; }
77 int note_value() const { return _note_value; }
79 inline bool operator==(const Meter& other) { return _divisions_per_bar == other.divisions_per_bar() && _note_value == other.note_value(); }
80 inline bool operator!=(const Meter& other) { return _divisions_per_bar != other.divisions_per_bar() || _note_value != other.note_value(); }
82 Meter& operator=(Meter const & other) {
84 _divisions_per_bar = other._divisions_per_bar;
85 _note_value = other._note_value;
90 Timecode::BBT_Time bbt_add (Timecode::BBT_Time const & bbt, Timecode::BBT_Offset const & add) const;
91 Timecode::BBT_Time bbt_subtract (Timecode::BBT_Time const & bbt, Timecode::BBT_Offset const & sub) const;
92 Timecode::BBT_Offset bbt_delta (Timecode::BBT_Time const & bbt, Timecode::BBT_Time const & sub) const;
94 Timecode::BBT_Time round_up_to_bar (Timecode::BBT_Time const &) const;
95 Timecode::BBT_Time round_down_to_bar (Timecode::BBT_Time const &) const;
96 Timecode::BBT_Time round_to_bar (Timecode::BBT_Time const &) const;
98 Temporal::Beats to_quarters (Timecode::BBT_Offset const &) const;
101 /** The type of "note" that a division represents. For example, 4 is
102 a quarter (crotchet) note, 8 is an eighth (quaver) note, etc.
105 /* how many of '_note_value' make up a bar or measure */
106 int8_t _divisions_per_bar;
109 /** Helper class to keep track of the Meter *AND* Tempo in effect
110 at a given point in time.
112 class LIBARDOUR_API TempoMetric : public Tempo, public Meter {
114 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) {}
117 double c_per_superclock () const { return _c_per_superclock; }
118 double c_per_quarter () const { return _c_per_quarter; }
120 void compute_c_superclock (samplecnt_t sr, superclock_t end_superclocks_per_note_type, superclock_t duration);
121 void compute_c_quarters (samplecnt_t sr, superclock_t end_superclocks_per_note_type, Temporal::Beats const & duration);
123 superclock_t superclocks_per_bar (samplecnt_t sr) const;
124 superclock_t superclocks_per_grid (samplecnt_t sr) const;
126 superclock_t superclock_at_qn (Temporal::Beats const & qn) const;
127 superclock_t superclock_per_note_type_at_superclock (superclock_t) const;
129 bool ramped () const { return _ramped; }
130 void set_ramped (bool yn) { _ramped = yn; } /* caller must mark something dirty to force recompute */
133 double _c_per_quarter;
134 double _c_per_superclock;
138 /** Tempo Map - mapping of timecode to musical time.
139 * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo
144 we have several different ways of talking about time:
146 * PULSE : whole notes, just because. These are linearly related to any other
147 note type, so if you know a number of pulses (whole notes), you
148 know the corresponding number of any other note type (e.g. quarter
151 * QUARTER NOTES : just what the name says. A lot of MIDI software and
152 concepts assume that a "beat" is a quarter-note.
154 * BEAT : a fraction of a PULSE. Defined by the meter in effect, so requires
155 meter (time signature) information to convert to/from PULSE or QUARTER NOTES.
156 In a 5/8 time, a BEAT is 1/8th note. In a 4/4 time, a beat is quarter note.
157 This means that measuring time in BEATS is potentially non-linear (if
158 the time signature changes, there will be a different number of BEATS
159 corresponding to a given time in any other unit).
161 * SUPERCLOCK : a very high resolution clock whose frequency
162 has as factors all common sample rates and all common note
163 type divisors. Related to MINUTES or SAMPLES only when a
164 sample rate is known. Related to PULSE or QUARTER NOTES only
165 when a tempo is known.
167 * MINUTES : wallclock time measurement. related to SAMPLES or SUPERCLOCK
168 only when a sample rate is known.
171 * SAMPLES : audio time measurement. Related to MINUTES or SUPERCLOCK only
172 when a sample rate is known
174 * BBT : bars|beats|ticks ... linearly related to BEATS but with the added
175 semantics of bars ("measures") added, in which beats are broken up
176 into groups of bars ("measures"). Requires meter (time signature)
177 information to compute to/from a given BEATS value. Contains no
178 additional time information compared to BEATS, but does have
179 additional semantic information.
181 Nick sez: not every note onset is on a tick
182 Paul wonders: if it's 8 samples off, does it matter?
183 Nick sez: it should not phase with existing audio
187 class LIBARDOUR_API TempoMapPoint
195 TempoMapPoint (Flag f, Tempo const& t, Meter const& m, superclock_t sc, Temporal::Beats const & q, Timecode::BBT_Time const & bbt, PositionLockStyle psl, bool ramp = false)
196 : _flags (f), _explicit (t, m, psl, ramp), _sclock (sc), _quarters (q), _bbt (bbt), _dirty (true), _map (0) {}
197 TempoMapPoint (TempoMapPoint const & tmp, superclock_t sc, Temporal::Beats const & q, Timecode::BBT_Time const & bbt)
198 : _flags (Flag (0)), _reference (&tmp), _sclock (sc), _quarters (q), _bbt (bbt), _dirty (true), _map (0) {}
201 void set_map (TempoMap* m);
203 Flag flags() const { return _flags; }
204 bool is_explicit() const { return _flags != Flag (0); }
205 bool is_implicit() const { return _flags == Flag (0); }
207 superclock_t superclocks_per_note_type (int8_t note_type) const {
209 return _explicit.metric.superclocks_per_note_type (note_type);
211 return _reference->superclocks_per_note_type (note_type);
214 struct BadTempoMetricLookup : public std::exception {
215 virtual const char* what() const throw() { return "cannot obtain non-const Metric from implicit map point"; }
218 bool dirty() const { return _dirty; }
220 superclock_t sclock() const { return _sclock; }
221 Temporal::Beats const & quarters() const { return _quarters; }
222 Timecode::BBT_Time const & bbt() const { return _bbt; }
223 bool ramped() const { return metric().ramped(); }
224 TempoMetric const & metric() const { return is_explicit() ? _explicit.metric : _reference->metric(); }
225 PositionLockStyle lock_style() const { return is_explicit() ? _explicit.lock_style : _reference->lock_style(); }
227 void compute_c_superclock (samplecnt_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); } }
228 void compute_c_quarters (samplecnt_t sr, superclock_t end_superclocks_per_note_type, Temporal::Beats const & duration) { if (is_explicit()) { _explicit.metric.compute_c_quarters (sr, end_superclocks_per_note_type, duration); } }
230 /* None of these properties can be set for an Implicit point, because
231 * they are determined by the TempoMapPoint pointed to by _reference.
234 void set_sclock (superclock_t sc) { if (is_explicit()) { _sclock = sc; _dirty = true; } }
235 void set_quarters (Temporal::Beats const & q) { if (is_explicit()) { _quarters = q; _dirty = true; } }
236 void set_bbt (Timecode::BBT_Time const & bbt) { if (is_explicit()) { _bbt = bbt; _dirty = true; } }
237 void set_dirty (bool yn);
238 void set_lock_style (PositionLockStyle psl) { if (is_explicit()) { _explicit.lock_style = psl; _dirty = true; } }
240 void make_explicit (Flag f) {
241 _flags = Flag (_flags|f);
242 /* since _metric and _reference are part of an anonymous union,
243 avoid possible compiler glitches by copying to a stack
244 variable first, then assign.
246 TempoMetric tm (_explicit.metric);
247 _explicit.metric = tm;
251 void make_implicit (TempoMapPoint & tmp) { _flags = Flag (0); _reference = &tmp; }
253 Temporal::Beats quarters_at (superclock_t sc) const;
254 Temporal::Beats quarters_at (Timecode::BBT_Time const &) const;
256 Timecode::BBT_Time bbt_at (Temporal::Beats const &) const;
259 XMLNode& get_state() const;
260 int set_state (XMLNode const&, int version);
263 struct SuperClockComparator {
264 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.sclock() < b.sclock(); }
267 struct QuarterComparator {
268 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.quarters() < b.quarters(); }
271 struct BBTComparator {
272 bool operator() (TempoMapPoint const & a, TempoMapPoint const & b) const { return a.bbt() < b.bbt(); }
276 friend class TempoMap;
277 void map_reset_set_sclock_for_sr_change (superclock_t sc) { _sclock = sc; }
280 struct ExplicitInfo {
281 ExplicitInfo (Tempo const & t, Meter const & m, PositionLockStyle psl, bool ramp) : metric (t, m, ramp), lock_style (psl) {}
284 PositionLockStyle lock_style;
289 TempoMapPoint const * _reference;
290 ExplicitInfo _explicit;
292 superclock_t _sclock;
293 Temporal::Beats _quarters;
294 Timecode::BBT_Time _bbt;
299 typedef std::list<TempoMapPoint> TempoMapPoints;
301 class LIBARDOUR_API TempoMap
304 TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, samplecnt_t sr);
306 void set_dirty (bool yn);
308 void set_sample_rate (samplecnt_t sr);
309 samplecnt_t sample_rate() const { return _sample_rate; }
311 void remove_explicit_point (superclock_t);
313 bool move_to (superclock_t current, superclock_t destination, bool push = false);
315 bool set_tempo_and_meter (Tempo const &, Meter const &, superclock_t, bool ramp, bool flexible);
317 bool set_tempo (Tempo const &, Timecode::BBT_Time const &, bool ramp = false);
318 bool set_tempo (Tempo const &, superclock_t, bool ramp = false);
320 bool set_meter (Meter const &, Timecode::BBT_Time const &);
321 bool set_meter (Meter const &, superclock_t);
323 Meter const & meter_at (superclock_t sc) const;
324 Meter const & meter_at (Temporal::Beats const & b) const;
325 Meter const & meter_at (Timecode::BBT_Time const & bbt) const;
326 Tempo const & tempo_at (superclock_t sc) const;
327 Tempo const & tempo_at (Temporal::Beats const &b) const;
328 Tempo const & tempo_at (Timecode::BBT_Time const & bbt) const;
330 Timecode::BBT_Time bbt_at (superclock_t sc) const;
331 Timecode::BBT_Time bbt_at (Temporal::Beats const &) const;
332 Temporal::Beats quarter_note_at (superclock_t sc) const;
333 Temporal::Beats quarter_note_at (Timecode::BBT_Time const &) const;
334 superclock_t superclock_at (Temporal::Beats const &) const;
335 superclock_t superclock_at (Timecode::BBT_Time const &) const;
337 TempoMapPoint const & const_point_at (superclock_t sc) const { return *const_iterator_at (sc); }
338 TempoMapPoint const & const_point_at (Temporal::Beats const & b) const { return *const_iterator_at (b); }
339 TempoMapPoint const & const_point_at (Timecode::BBT_Time const & bbt) const { return *const_iterator_at (bbt); }
341 TempoMapPoint const & const_point_after (superclock_t sc) const;
342 TempoMapPoint const & const_point_after (Temporal::Beats const & b) const;
343 TempoMapPoint const & const_point_after (Timecode::BBT_Time const & bbt) const;
345 /* If resolution == Temporal::Beats() (i.e. zero), then the grid that is
346 returned will contain a mixture of implicit and explicit points,
347 and will only be valid as long as this map remains unchanged
348 (because the implicit points may reference explicit points in the
351 If resolution != Temporal::Beats() (i.e. non-zero), then the in-out @param
352 grid will contain only explicit points that do not reference this
355 void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end, Temporal::Beats const & resolution);
357 void get_bar_grid (TempoMapPoints& points, superclock_t start, superclock_t end, int32_t bar_gap);
359 struct EmptyTempoMapException : public std::exception {
360 virtual const char* what() const throw() { return "TempoMap is empty"; }
363 void dump (std::ostream&);
364 void rebuild (superclock_t limit);
366 PBD::Signal2<void,superclock_t,superclock_t> Changed;
369 TempoMapPoints _points;
370 samplecnt_t _sample_rate;
371 mutable Glib::Threads::RWLock _lock;
374 /* these return an iterator that refers to the TempoMapPoint at or most immediately preceding the given position.
376 * Conceptually, these could be const methods, but C++ prevents them returning a non-const iterator in that case.
378 * Note that they cannot return an invalid iterator (e.g. _points.end()) because:
380 * - if the map is empty, an exception is thrown
381 * - if the given time is before the first map entry, _points.begin() is returned
382 * - if the given time is after the last map entry, the equivalent of _points.rbegin() is returned
383 * - if the given time is within the map entries, a valid iterator will be returned
386 TempoMapPoints::iterator iterator_at (superclock_t sc);
387 TempoMapPoints::iterator iterator_at (Temporal::Beats const &);
388 TempoMapPoints::iterator iterator_at (Timecode::BBT_Time const &);
390 TempoMapPoints::const_iterator const_iterator_at (superclock_t sc) const { return const_cast<TempoMap*>(this)->iterator_at (sc); }
391 TempoMapPoints::const_iterator const_iterator_at (Temporal::Beats const & b) const { return const_cast<TempoMap*>(this)->iterator_at (b); }
392 TempoMapPoints::const_iterator const_iterator_at (Timecode::BBT_Time const & bbt) const { return const_cast<TempoMap*>(this)->iterator_at (bbt); }
394 /* Returns the TempoMapPoint at or most immediately preceding the given time. If the given time is
395 * before the first map entry, then the first map entry will be returned, which underlies the semantics
396 * that the first map entry's values propagate backwards in time if not at absolute zero.
398 * As for iterator_at(), define both const+const and non-const variants, because C++ won't let us return a non-const iterator
399 from a const method (which is a bit silly, but presumably aids compiler reasoning).
402 TempoMapPoint & point_at (superclock_t sc) { return *iterator_at (sc); }
403 TempoMapPoint & point_at (Temporal::Beats const & b) { return *iterator_at (b); }
404 TempoMapPoint & point_at (Timecode::BBT_Time const & bbt) { return *iterator_at (bbt); }
406 Meter const & meter_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
407 Meter const & meter_at_locked (Temporal::Beats const & b) const { return const_point_at (b).metric(); }
408 Meter const & meter_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
409 Tempo const & tempo_at_locked (superclock_t sc) const { return const_point_at (sc).metric(); }
410 Tempo const & tempo_at_locked (Temporal::Beats const &b) const { return const_point_at (b).metric(); }
411 Tempo const & tempo_at_locked (Timecode::BBT_Time const & bbt) const { return const_point_at (bbt).metric(); }
412 Timecode::BBT_Time bbt_at_locked (superclock_t sc) const;
413 Timecode::BBT_Time bbt_at_locked (Temporal::Beats const &) const;
414 Temporal::Beats quarter_note_at_locked (superclock_t sc) const;
415 Temporal::Beats quarter_note_at_locked (Timecode::BBT_Time const &) const;
416 superclock_t superclock_at_locked (Temporal::Beats const &) const;
417 superclock_t superclock_at_locked (Timecode::BBT_Time const &) const;
419 void rebuild_locked (superclock_t limit);
420 void dump_locked (std::ostream&);
425 std::ostream& operator<<(std::ostream&, ARDOUR::TempoMapPoint const &);
426 std::ostream& operator<<(std::ostream&, ARDOUR::Tempo const &);
427 std::ostream& operator<<(std::ostream&, ARDOUR::Meter const &);
429 #endif /* __ardour_tempo_h__ */