convert codebase to use Temporal for various time types
[ardour.git] / libs / ardour / ardour / tempo.h
1 /*
2     Copyright (C) 2000 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __ardour_tempo_h__
21 #define __ardour_tempo_h__
22
23 #include <list>
24 #include <string>
25 #include <vector>
26 #include <cmath>
27 #include <glibmm/threads.h>
28
29 #include "pbd/undo.h"
30 #include "pbd/enum_convert.h"
31
32 #include "pbd/stateful.h"
33 #include "pbd/statefuldestructible.h"
34
35 #include "temporal/beats.h"
36
37 #include "ardour/ardour.h"
38
39 class BBTTest;
40 class FrameposPlusBeatsTest;
41 class FrameposMinusBeatsTest;
42 class TempoTest;
43 class XMLNode;
44
45 namespace ARDOUR {
46
47 class Meter;
48 class TempoMap;
49
50 // Find a better place for these
51 LIBARDOUR_API bool bbt_time_to_string (const Timecode::BBT_Time& bbt, std::string& str);
52 LIBARDOUR_API bool string_to_bbt_time (const std::string& str, Timecode::BBT_Time& bbt);
53
54 /** Tempo, the speed at which musical time progresses (BPM). */
55 class LIBARDOUR_API Tempo {
56   public:
57         /**
58          * @param npm Note Types per minute
59          * @param type Note Type (default `4': quarter note)
60          */
61         Tempo (double npm, double type=4.0) // defaulting to quarter note
62                 : _note_types_per_minute (npm), _note_type (type), _end_note_types_per_minute (npm) {}
63         Tempo (double start_npm, double type, double end_npm)
64                 : _note_types_per_minute (start_npm), _note_type (type), _end_note_types_per_minute (end_npm) {}
65
66         double note_types_per_minute () const { return _note_types_per_minute; }
67         double note_types_per_minute (double note_type) const { return (_note_types_per_minute / _note_type) * note_type; }
68         void set_note_types_per_minute (double npm) { _note_types_per_minute = npm; }
69         double note_type () const { return _note_type; }
70
71         double quarter_notes_per_minute () const { return note_types_per_minute (4.0); }
72         double pulses_per_minute () const { return note_types_per_minute (1.0); }
73
74         double end_note_types_per_minute () const { return _end_note_types_per_minute; }
75         double end_note_types_per_minute (double note_type) const { return (_end_note_types_per_minute / _note_type) * note_type; }
76         void set_end_note_types_per_minute (double npm) { _end_note_types_per_minute = npm; }
77
78         double end_quarter_notes_per_minute () const { return end_note_types_per_minute (4.0); }
79         double end_pulses_per_minute () const { return end_note_types_per_minute (1.0); }
80
81         /** audio samples per note type.
82          * if you want an instantaneous value for this, use TempoMap::samples_per_quarter_note_at() instead.
83          * @param sr samplerate
84          */
85         double samples_per_note_type (samplecnt_t sr) const {
86                 return (60.0 * sr) / _note_types_per_minute;
87         }
88         /** audio samples per quarter note.
89          * if you want an instantaneous value for this, use TempoMap::samples_per_quarter_note_at() instead.
90          * @param sr samplerate
91          */
92         double samples_per_quarter_note (samplecnt_t sr) const {
93                 return (60.0 * sr) / quarter_notes_per_minute ();
94         }
95
96   protected:
97         double _note_types_per_minute;
98         double _note_type;
99         double _end_note_types_per_minute;
100 };
101
102 /** Meter, or time signature (beats per bar, and which note type is a beat). */
103 class LIBARDOUR_API Meter {
104   public:
105         Meter (double dpb, double bt)
106                 : _divisions_per_bar (dpb), _note_type (bt) {}
107
108         double divisions_per_bar () const { return _divisions_per_bar; }
109         double note_divisor() const { return _note_type; }
110
111         double samples_per_bar (const Tempo&, samplecnt_t sr) const;
112         double samples_per_grid (const Tempo&, samplecnt_t sr) const;
113
114         inline bool operator==(const Meter& other)
115         { return _divisions_per_bar == other.divisions_per_bar() && _note_type == other.note_divisor(); }
116
117   protected:
118         /** The number of divisions in a bar.  This is a floating point value because
119             there are musical traditions on our planet that do not limit
120             themselves to integral numbers of beats per bar.
121         */
122         double _divisions_per_bar;
123
124         /** The type of "note" that a division represents.  For example, 4.0 is
125             a quarter (crotchet) note, 8.0 is an eighth (quaver) note, etc.
126         */
127         double _note_type;
128 };
129
130 /** A section of timeline with a certain Tempo or Meter. */
131 class LIBARDOUR_API MetricSection {
132   public:
133         MetricSection (double pulse, double minute, PositionLockStyle pls, bool is_tempo, samplecnt_t sample_rate)
134                 : _pulse (pulse), _minute (minute), _initial (false), _position_lock_style (pls), _is_tempo (is_tempo), _sample_rate (sample_rate) {}
135
136         virtual ~MetricSection() {}
137
138         const double& pulse () const { return _pulse; }
139         void set_pulse (double pulse) { _pulse = pulse; }
140
141         double minute() const { return _minute; }
142         virtual void set_minute (double m) {
143                 _minute = m;
144         }
145
146         samplepos_t sample () const { return sample_at_minute (_minute); }
147
148         void set_initial (bool yn) { _initial = yn; }
149         bool initial() const { return _initial; }
150
151         /* MeterSections are not stateful in the full sense,
152            but we do want them to control their own
153            XML state information.
154         */
155         virtual XMLNode& get_state() const = 0;
156
157         virtual int set_state (const XMLNode&, int version);
158
159         PositionLockStyle position_lock_style () const { return _position_lock_style; }
160         void set_position_lock_style (PositionLockStyle ps) { _position_lock_style = ps; }
161         bool is_tempo () const { return _is_tempo; }
162
163         samplepos_t sample_at_minute (const double& time) const;
164         double minute_at_sample (const samplepos_t sample) const;
165
166 protected:
167         void add_state_to_node (XMLNode& node) const;
168
169 private:
170
171         double             _pulse;
172         double             _minute;
173         bool               _initial;
174         PositionLockStyle  _position_lock_style;
175         const bool         _is_tempo;
176         samplecnt_t         _sample_rate;
177 };
178
179 /** A section of timeline with a certain Meter. */
180 class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
181   public:
182         MeterSection (double pulse, double minute, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type, PositionLockStyle pls, samplecnt_t sr)
183                 : MetricSection (pulse, minute, pls, false, sr), Meter (bpb, note_type), _bbt (bbt),  _beat (beat) {}
184
185         MeterSection (const XMLNode&, const samplecnt_t sample_rate);
186
187         static const std::string xml_state_node_name;
188
189         XMLNode& get_state() const;
190
191         void set_beat (std::pair<double, Timecode::BBT_Time>& w) {
192                 _beat = w.first;
193                 _bbt = w.second;
194         }
195
196         const Timecode::BBT_Time& bbt() const { return _bbt; }
197         const double& beat () const { return _beat; }
198         void set_beat (double beat) { _beat = beat; }
199
200 private:
201         Timecode::BBT_Time _bbt;
202         double _beat;
203 };
204
205 /** A section of timeline with a certain Tempo. */
206 class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
207   public:
208         enum Type {
209                 Ramp,
210                 Constant,
211         };
212
213         TempoSection (const double& pulse, const double& minute, Tempo tempo, PositionLockStyle pls, samplecnt_t sr)
214                 : MetricSection (pulse, minute, pls, true, sr), Tempo (tempo), _c (0.0), _active (true), _locked_to_meter (false), _clamped (false)  {}
215
216         TempoSection (const XMLNode&, const samplecnt_t sample_rate);
217
218         static const std::string xml_state_node_name;
219
220         XMLNode& get_state() const;
221
222         double c () const { return _c; }
223         void set_c (double c) { _c = c; }
224
225         Type type () const { if (note_types_per_minute() == end_note_types_per_minute()) { return Constant; } else { return Ramp; } }
226
227         bool active () const { return _active; }
228         void set_active (bool yn) { _active = yn; }
229
230         bool locked_to_meter ()  const { return _locked_to_meter; }
231         void set_locked_to_meter (bool yn) { _locked_to_meter = yn; }
232
233         bool clamped ()  const { return _clamped; }
234         void set_clamped (bool yn) { _clamped = yn; }
235
236         Tempo tempo_at_minute (const double& minute) const;
237         double minute_at_ntpm (const double& ntpm, const double& pulse) const;
238
239         Tempo tempo_at_pulse (const double& pulse) const;
240         double pulse_at_ntpm (const double& ntpm, const double& minute) const;
241
242         double pulse_at_minute (const double& minute) const;
243         double minute_at_pulse (const double& pulse) const;
244
245         double compute_c_pulse (const double& end_ntpm, const double& end_pulse) const;
246         double compute_c_minute (const double& end_ntpm, const double& end_minute) const;
247
248         double pulse_at_sample (const samplepos_t sample) const;
249         samplepos_t sample_at_pulse (const double& pulse) const;
250
251         Timecode::BBT_Time legacy_bbt () { return _legacy_bbt; }
252
253   private:
254
255         /*  tempo ramp functions. zero-based with time in minutes,
256          * 'tick tempo' in ticks per minute and tempo in bpm.
257          *  time relative to section start.
258          */
259         double a_func (double end_tpm, double c_func) const;
260         double c_func (double end_tpm, double end_time) const;
261
262         double _tempo_at_time (const double& time) const;
263         double _time_at_tempo (const double& tempo) const;
264
265         double _tempo_at_pulse (const double& pulse) const;
266         double _pulse_at_tempo (const double& tempo) const;
267
268         double _pulse_at_time (const double& time) const;
269         double _time_at_pulse (const double& pulse) const;
270
271         /* this value provides a fractional offset into the bar in which
272            the tempo section is located in. A value of 0.0 indicates that
273            it occurs on the first beat of the bar, a value of 0.5 indicates
274            that it occurs halfway through the bar and so on.
275
276            this enables us to keep the tempo change at the same relative
277            position within the bar if/when the meter changes.
278         */
279
280         double _c;
281         bool _active;
282         bool _locked_to_meter;
283         bool _clamped;
284         Timecode::BBT_Time _legacy_bbt;
285 };
286
287 typedef std::list<MetricSection*> Metrics;
288
289 /** Helper class to keep track of the Meter *AND* Tempo in effect
290     at a given point in time.
291 */
292 class LIBARDOUR_API TempoMetric {
293   public:
294         TempoMetric (const Meter& m, const Tempo& t)
295                 : _meter (&m), _tempo (&t), _minute (0.0), _pulse (0.0) {}
296
297         void set_tempo (const Tempo& t)              { _tempo = &t; }
298         void set_meter (const Meter& m)              { _meter = &m; }
299         void set_minute (double m)                   { _minute = m; }
300         void set_pulse (const double& p)             { _pulse = p; }
301
302         void set_metric (const MetricSection* section) {
303                 const MeterSection* meter;
304                 const TempoSection* tempo;
305                 if ((meter = dynamic_cast<const MeterSection*>(section))) {
306                         set_meter(*meter);
307                 } else if ((tempo = dynamic_cast<const TempoSection*>(section))) {
308                         set_tempo(*tempo);
309                 }
310
311                 set_minute (section->minute());
312                 set_pulse (section->pulse());
313         }
314
315         const Meter&              meter() const { return *_meter; }
316         const Tempo&              tempo() const { return *_tempo; }
317         double                    minute() const { return _minute; }
318         const double&             pulse() const { return _pulse; }
319
320   private:
321         const Meter*       _meter;
322         const Tempo*       _tempo;
323         double             _minute;
324         double             _pulse;
325 };
326
327 /** Tempo Map - mapping of timecode to musical time.
328  * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo
329  */
330 class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
331 {
332   public:
333         TempoMap (samplecnt_t sample_rate);
334         ~TempoMap();
335
336         TempoMap& operator= (TempoMap const &);
337
338         /* measure-based stuff */
339
340         enum BBTPointType {
341                 Bar,
342                 Beat,
343         };
344
345         struct BBTPoint {
346                 Meter               meter;
347                 Tempo               tempo;
348                 samplepos_t          sample;
349                 uint32_t            bar;
350                 uint32_t            beat;
351                 double              qn;
352
353                 BBTPoint (const MeterSection& m, const Tempo& t, samplepos_t f,
354                           uint32_t b, uint32_t e, double qnote)
355                 : meter (m), tempo (t), sample (f), bar (b), beat (e), qn (qnote) {}
356
357                 Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
358                 operator Timecode::BBT_Time() const { return bbt(); }
359                 operator samplepos_t() const { return sample; }
360                 bool is_bar() const { return beat == 1; }
361         };
362
363         template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
364                 Glib::Threads::RWLock::ReaderLock lm (lock);
365                 (obj.*method)(_metrics);
366         }
367
368         void get_grid (std::vector<BBTPoint>&,
369                        samplepos_t start, samplepos_t end, uint32_t bar_mod = 0);
370
371         static const Tempo& default_tempo() { return _default_tempo; }
372         static const Meter& default_meter() { return _default_meter; }
373
374         /* because tempi may be ramped, this is only valid for the instant requested.*/
375         double samples_per_quarter_note_at (const samplepos_t, const samplecnt_t sr) const;
376
377         const TempoSection& tempo_section_at_sample (samplepos_t sample) const;
378         TempoSection& tempo_section_at_sample (samplepos_t sample);
379         const MeterSection& meter_section_at_sample (samplepos_t sample) const;
380         const MeterSection& meter_section_at_beat (double beat) const;
381
382         TempoSection* previous_tempo_section (TempoSection*) const;
383         TempoSection* next_tempo_section (TempoSection*) const;
384
385         /** add a tempo section locked to pls. ignored values will be set in recompute_tempi()
386          * @param pulse pulse position of new section. ignored if pls == AudioTime
387          * @param sample frame position of new section. ignored if pls == MusicTime
388          * @param type type of new tempo section (Ramp, Constant)
389          */
390         TempoSection* add_tempo (const Tempo&, const double& pulse, const samplepos_t sample, PositionLockStyle pls);
391
392         /** add a meter section locked to pls.. ignored values will be set in recompute_meters()
393          * @param meter the Meter to be added
394          * @param where bbt position of new section
395          * @param sample frame position of new section. ignored if pls == MusicTime
396          * note that @sample may also be ignored if it would create an un-solvable map
397          * (previous audio-locked tempi may place the requested beat at an earlier time than sample)
398          * in which case the new meter will be placed at the specified BBT.
399          * @param  pls the position lock style
400          *
401          * adding an audio-locked meter will add a meter-locked tempo section at the meter position.
402          * the meter-locked tempo tempo will be the Tempo at @beat
403          */
404         MeterSection* add_meter (const Meter& meter, const Timecode::BBT_Time& where, samplepos_t sample, PositionLockStyle pls);
405
406         void remove_tempo (const TempoSection&, bool send_signal);
407         void remove_meter (const MeterSection&, bool send_signal);
408
409         void replace_tempo (TempoSection&, const Tempo&, const double& pulse, const samplepos_t sample, PositionLockStyle pls);
410
411         void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, samplepos_t sample, PositionLockStyle pls);
412
413         MusicSample round_to_bar  (samplepos_t sample, RoundMode dir);
414         MusicSample round_to_beat (samplepos_t sample, RoundMode dir);
415         MusicSample round_to_quarter_note_subdivision (samplepos_t fr, int sub_num, RoundMode dir);
416
417         void set_length (samplepos_t samples);
418
419         XMLNode& get_state (void);
420         int set_state (const XMLNode&, int version);
421
422         void dump (std::ostream&) const;
423         void clear ();
424
425         TempoMetric metric_at (Timecode::BBT_Time bbt) const;
426
427         /** Return the TempoMetric at sample @p t, and point @p last to the latest
428          * metric change <= t, if it is non-NULL.
429          */
430         TempoMetric metric_at (samplepos_t, Metrics::const_iterator* last=NULL) const;
431
432         Metrics::const_iterator metrics_end() { return _metrics.end(); }
433
434         void change_existing_tempo_at (samplepos_t, double bpm, double note_type, double end_ntpm);
435         void change_initial_tempo (double ntpm, double note_type, double end_ntpm);
436
437         void insert_time (samplepos_t, samplecnt_t);
438         bool remove_time (samplepos_t where, samplecnt_t amount);  //returns true if anything was moved
439
440         int n_tempos () const;
441         int n_meters () const;
442
443         samplecnt_t sample_rate () const { return _sample_rate; }
444
445         /* TEMPO- AND METER-SENSITIVE FUNCTIONS
446
447            bbt_at_sample(), sample_at_bbt(), beat_at_sample(), sample_at_beat()
448            and bbt_duration_at()
449            are all sensitive to tempo and meter, and will give answers
450            that align with the grid formed by tempo and meter sections.
451
452            They SHOULD NOT be used to determine the position of events
453            whose location is canonically defined in Temporal::Beats.
454         */
455
456         double beat_at_sample (const samplecnt_t sample) const;
457         samplepos_t sample_at_beat (const double& beat) const;
458
459         const Meter& meter_at_sample (samplepos_t) const;
460
461         /* bbt - it's nearly always better to use meter-based beat (above)
462            unless tick resolution is desirable.
463         */
464         Timecode::BBT_Time bbt_at_sample (samplepos_t when);
465         Timecode::BBT_Time bbt_at_sample_rt (samplepos_t when);
466         samplepos_t sample_at_bbt (const Timecode::BBT_Time&);
467
468         double beat_at_bbt (const Timecode::BBT_Time& bbt);
469         Timecode::BBT_Time bbt_at_beat (const double& beats);
470
471         double quarter_note_at_bbt (const Timecode::BBT_Time& bbt);
472         double quarter_note_at_bbt_rt (const Timecode::BBT_Time& bbt);
473         Timecode::BBT_Time bbt_at_quarter_note (const double& quarter_note);
474
475         samplecnt_t bbt_duration_at (samplepos_t, const Timecode::BBT_Time&, int dir);
476         samplepos_t samplepos_plus_bbt (samplepos_t pos, Timecode::BBT_Time b) const;
477
478         /* TEMPO-SENSITIVE FUNCTIONS
479
480            These next 2 functions will all take tempo in account and should be
481            used to determine position (and in the last case, distance in beats)
482            when tempo matters but meter does not.
483
484            They SHOULD be used to determine the position of events
485            whose location is canonically defined in Temporal::Beats.
486         */
487
488         samplepos_t samplepos_plus_qn (samplepos_t, Temporal::Beats) const;
489         Temporal::Beats framewalk_to_qn (samplepos_t pos, samplecnt_t distance) const;
490
491         /* quarter note related functions are also tempo-sensitive and ignore meter.
492            quarter notes may be compared with and assigned to Temporal::Beats.
493         */
494         double quarter_note_at_sample (const samplepos_t sample) const;
495         double quarter_note_at_sample_rt (const samplepos_t sample) const;
496         samplepos_t sample_at_quarter_note (const double quarter_note) const;
497
498         samplecnt_t samples_between_quarter_notes (const double start, const double end) const;
499         double     quarter_notes_between_samples (const samplecnt_t start, const samplecnt_t end) const;
500
501         double quarter_note_at_beat (const double beat) const;
502         double beat_at_quarter_note (const double beat) const;
503
504         /* obtain a musical subdivision via a sample position and magic note divisor.*/
505         double exact_qn_at_sample (const samplepos_t sample, const int32_t sub_num) const;
506         double exact_beat_at_sample (const samplepos_t sample, const int32_t sub_num) const;
507
508         Tempo tempo_at_sample (const samplepos_t sample) const;
509         samplepos_t sample_at_tempo (const Tempo& tempo) const;
510         Tempo tempo_at_quarter_note (const double& beat) const;
511         double quarter_note_at_tempo (const Tempo& tempo) const;
512
513         void gui_set_tempo_position (TempoSection*, const samplepos_t sample, const int& sub_num);
514         void gui_set_meter_position (MeterSection*, const samplepos_t sample);
515         bool gui_change_tempo (TempoSection*, const Tempo& bpm);
516         void gui_stretch_tempo (TempoSection* tempo, const samplepos_t sample, const samplepos_t end_sample, const double start_qnote, const double end_qnote);
517         void gui_stretch_tempo_end (TempoSection* tempo, const samplepos_t sample, const samplepos_t end_sample);
518         bool gui_twist_tempi (TempoSection* first, const Tempo& bpm, const samplepos_t sample, const samplepos_t end_sample);
519
520         std::pair<double, samplepos_t> predict_tempo_position (TempoSection* section, const Timecode::BBT_Time& bbt);
521         bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt);
522
523         PBD::Signal1<void,const PBD::PropertyChange&> MetricPositionChanged;
524         void fix_legacy_session();
525         void fix_legacy_end_session();
526
527         samplepos_t music_origin ();
528
529 private:
530         /* prevent copy construction */
531         TempoMap (TempoMap const&);
532
533         TempoSection* previous_tempo_section_locked (const Metrics& metrics, TempoSection*) const;
534         TempoSection* next_tempo_section_locked (const Metrics& metrics, TempoSection*) const;
535
536         double beat_at_minute_locked (const Metrics& metrics, const double& minute) const;
537         double minute_at_beat_locked (const Metrics& metrics, const double& beat) const;
538
539         double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
540         double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
541
542         double pulse_at_minute_locked (const Metrics& metrics, const double& minute) const;
543         double minute_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
544
545         Tempo tempo_at_minute_locked (const Metrics& metrics, const double& minute) const;
546         double minute_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
547
548         Tempo tempo_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
549         double pulse_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
550
551         Timecode::BBT_Time bbt_at_minute_locked (const Metrics& metrics, const double& minute) const;
552         double minute_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
553
554         double beat_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
555         Timecode::BBT_Time bbt_at_beat_locked (const Metrics& metrics, const double& beats) const;
556
557         double pulse_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const;
558         Timecode::BBT_Time bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
559
560         double minutes_between_quarter_notes_locked (const Metrics& metrics, const double start_qn, const double end_qn) const;
561         double quarter_notes_between_samples_locked (const Metrics& metrics, const samplecnt_t  start, const samplecnt_t end) const;
562
563         const TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute) const;
564         TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute);
565         const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
566
567         const MeterSection& meter_section_at_minute_locked (const Metrics& metrics, double minute) const;
568         const MeterSection& meter_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
569
570         bool check_solved (const Metrics& metrics) const;
571         bool set_active_tempi (const Metrics& metrics, const samplepos_t sample);
572
573         bool solve_map_minute (Metrics& metrics, TempoSection* section, const double& minute);
574         bool solve_map_pulse (Metrics& metrics, TempoSection* section, const double& pulse);
575         bool solve_map_minute (Metrics& metrics, MeterSection* section, const double& minute);
576         bool solve_map_bbt (Metrics& metrics, MeterSection* section, const Timecode::BBT_Time& bbt);
577
578         double exact_beat_at_sample_locked (const Metrics& metrics, const samplepos_t sample, const int32_t sub_num) const;
579         double exact_qn_at_sample_locked (const Metrics& metrics, const samplepos_t sample, const int32_t sub_num) const;
580
581         double minute_at_sample (const samplepos_t sample) const;
582         samplepos_t sample_at_minute (const double minute) const;
583
584         friend class ::BBTTest;
585         friend class ::FrameposPlusBeatsTest;
586         friend class ::FrameposMinusBeatsTest;
587         friend class ::TempoTest;
588
589         static Tempo    _default_tempo;
590         static Meter    _default_meter;
591
592         Metrics                       _metrics;
593         samplecnt_t                    _sample_rate;
594         mutable Glib::Threads::RWLock lock;
595
596         void recompute_tempi (Metrics& metrics);
597         void recompute_meters (Metrics& metrics);
598         void recompute_map (Metrics& metrics, samplepos_t end = -1);
599
600         MusicSample round_to_type (samplepos_t fr, RoundMode dir, BBTPointType);
601
602         const MeterSection& first_meter() const;
603         MeterSection&       first_meter();
604         const TempoSection& first_tempo() const;
605         TempoSection&       first_tempo();
606
607         void do_insert (MetricSection* section);
608
609         TempoSection* add_tempo_locked (const Tempo&, double pulse, double minute
610                                         , PositionLockStyle pls, bool recompute, bool locked_to_meter = false, bool clamped = false);
611
612         MeterSection* add_meter_locked (const Meter&, const Timecode::BBT_Time& where, samplepos_t sample, PositionLockStyle pls, bool recompute);
613
614         bool remove_tempo_locked (const TempoSection&);
615         bool remove_meter_locked (const MeterSection&);
616
617         TempoSection* copy_metrics_and_point (const Metrics& metrics, Metrics& copy, TempoSection* section) const;
618         MeterSection* copy_metrics_and_point (const Metrics& metrics, Metrics& copy, MeterSection* section) const;
619 };
620
621 }; /* namespace ARDOUR */
622
623 LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
624 LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
625 LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
626
627 namespace PBD {
628         DEFINE_ENUM_CONVERT (ARDOUR::TempoSection::Type)
629 }
630
631 #endif /* __ardour_tempo_h__ */