da68f6516e127e0af653a1068653bd3600e31ae9
[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 "evoral/Beats.hpp"
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::frames_per_quarter_note_at() instead.
83          * @param sr samplerate
84          */
85         double frames_per_note_type (framecnt_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::frames_per_quarter_note_at() instead.
90          * @param sr samplerate
91          */
92         double frames_per_quarter_note (framecnt_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 frames_per_bar (const Tempo&, framecnt_t sr) const;
112         double frames_per_grid (const Tempo&, framecnt_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, framecnt_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         framepos_t frame () const { return frame_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         framepos_t frame_at_minute (const double& time) const;
164         double minute_at_frame (const framepos_t& frame) 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         framecnt_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, framecnt_t sr)
183                 : MetricSection (pulse, minute, pls, false, sr), Meter (bpb, note_type), _bbt (bbt),  _beat (beat) {}
184
185         MeterSection (const XMLNode&, const framecnt_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, framecnt_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 framecnt_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_frame (const framepos_t& frame) const;
249         framepos_t frame_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 (framecnt_t frame_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                 framepos_t          frame;
349                 uint32_t            bar;
350                 uint32_t            beat;
351                 double              qn;
352
353                 BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f,
354                           uint32_t b, uint32_t e, double qnote)
355                 : meter (m), tempo (t), frame (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 framepos_t() const { return frame; }
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                        framepos_t start, framepos_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 frames_per_quarter_note_at (const framepos_t&, const framecnt_t& sr) const;
376
377         const TempoSection& tempo_section_at_frame (framepos_t frame) const;
378         TempoSection& tempo_section_at_frame (framepos_t frame);
379         const MeterSection& meter_section_at_frame (framepos_t frame) 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 frame 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 framepos_t& frame, 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 beat beat position of new section
395          * @param where bbt position of new section
396          * @param frame frame position of new section. ignored if pls == MusicTime
397          * note that @frame may also be ignored if it would create an un-solvable map
398          * (previous audio-locked tempi may place the requested beat at an earlier time than frame)
399          * in which case the new meter will be placed at the specified BBT.
400          * @param  pls the position lock style
401          *
402          * adding an audio-locked meter will add a meter-locked tempo section at the meter position.
403          * the meter-locked tempo tempo will be the Tempo at @beat
404          */
405         MeterSection* add_meter (const Meter& meter, const double& beat, const Timecode::BBT_Time& where, framepos_t frame, PositionLockStyle pls);
406
407         void remove_tempo (const TempoSection&, bool send_signal);
408         void remove_meter (const MeterSection&, bool send_signal);
409
410         void replace_tempo (TempoSection&, const Tempo&, const double& pulse, const framepos_t& frame, PositionLockStyle pls);
411
412         void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, framepos_t frame, PositionLockStyle pls);
413
414         MusicFrame round_to_bar  (framepos_t frame, RoundMode dir);
415         MusicFrame round_to_beat (framepos_t frame, RoundMode dir);
416         MusicFrame round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir);
417
418         void set_length (framepos_t frames);
419
420         XMLNode& get_state (void);
421         int set_state (const XMLNode&, int version);
422
423         void dump (std::ostream&) const;
424         void clear ();
425
426         TempoMetric metric_at (Timecode::BBT_Time bbt) const;
427
428         /** Return the TempoMetric at frame @p t, and point @p last to the latest
429          * metric change <= t, if it is non-NULL.
430          */
431         TempoMetric metric_at (framepos_t, Metrics::const_iterator* last=NULL) const;
432
433         Metrics::const_iterator metrics_end() { return _metrics.end(); }
434
435         void change_existing_tempo_at (framepos_t, double bpm, double note_type, double end_ntpm);
436         void change_initial_tempo (double ntpm, double note_type, double end_ntpm);
437
438         void insert_time (framepos_t, framecnt_t);
439         bool remove_time (framepos_t where, framecnt_t amount);  //returns true if anything was moved
440
441         int n_tempos () const;
442         int n_meters () const;
443
444         framecnt_t frame_rate () const { return _frame_rate; }
445
446         /* TEMPO- AND METER-SENSITIVE FUNCTIONS
447
448            bbt_at_frame(), frame_at_bbt(), beat_at_frame(), frame_at_beat()
449            and bbt_duration_at()
450            are all sensitive to tempo and meter, and will give answers
451            that align with the grid formed by tempo and meter sections.
452
453            They SHOULD NOT be used to determine the position of events
454            whose location is canonically defined in Evoral::Beats.
455         */
456
457         double beat_at_frame (const framecnt_t& frame) const;
458         framepos_t frame_at_beat (const double& beat) const;
459
460         const Meter& meter_at_frame (framepos_t) const;
461
462         /* bbt - it's nearly always better to use meter-based beat (above)
463            unless tick resolution is desirable.
464         */
465         Timecode::BBT_Time bbt_at_frame (framepos_t when);
466         Timecode::BBT_Time bbt_at_frame_rt (framepos_t when);
467         framepos_t frame_at_bbt (const Timecode::BBT_Time&);
468
469         double beat_at_bbt (const Timecode::BBT_Time& bbt);
470         Timecode::BBT_Time bbt_at_beat (const double& beats);
471
472         double quarter_note_at_bbt (const Timecode::BBT_Time& bbt);
473         double quarter_note_at_bbt_rt (const Timecode::BBT_Time& bbt);
474         Timecode::BBT_Time bbt_at_quarter_note (const double& quarter_note);
475
476         framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
477         framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
478
479         /* TEMPO-SENSITIVE FUNCTIONS
480
481            These next 2 functions will all take tempo in account and should be
482            used to determine position (and in the last case, distance in beats)
483            when tempo matters but meter does not.
484
485            They SHOULD be used to determine the position of events
486            whose location is canonically defined in Evoral::Beats.
487         */
488
489         framepos_t framepos_plus_qn (framepos_t, Evoral::Beats) const;
490         Evoral::Beats framewalk_to_qn (framepos_t pos, framecnt_t distance) const;
491
492         /* quarter note related functions are also tempo-sensitive and ignore meter.
493            quarter notes may be compared with and assigned to Evoral::Beats.
494         */
495         double quarter_note_at_frame (const framepos_t frame) const;
496         double quarter_note_at_frame_rt (const framepos_t frame) const;
497         framepos_t frame_at_quarter_note (const double quarter_note) const;
498
499         framecnt_t frames_between_quarter_notes (const double start, const double end) const;
500         double     quarter_notes_between_frames (const framecnt_t start, const framecnt_t end) const;
501
502         double quarter_note_at_beat (const double beat) const;
503         double beat_at_quarter_note (const double beat) const;
504
505         /* obtain a musical subdivision via a frame position and magic note divisor.*/
506         double exact_qn_at_frame (const framepos_t& frame, const int32_t sub_num) const;
507         double exact_beat_at_frame (const framepos_t& frame, const int32_t sub_num) const;
508
509         Tempo tempo_at_frame (const framepos_t& frame) const;
510         framepos_t frame_at_tempo (const Tempo& tempo) const;
511         Tempo tempo_at_quarter_note (const double& beat) const;
512         double quarter_note_at_tempo (const Tempo& tempo) const;
513
514         void gui_set_tempo_position (TempoSection*, const framepos_t& frame, const int& sub_num);
515         void gui_set_meter_position (MeterSection*, const framepos_t& frame);
516         bool gui_change_tempo (TempoSection*, const Tempo& bpm);
517         void gui_stretch_tempo (TempoSection* tempo, const framepos_t frame, const framepos_t end_frame);
518         void gui_stretch_tempo_end (TempoSection* tempo, const framepos_t frame, const framepos_t end_frame);
519         bool gui_twist_tempi (TempoSection* first, const Tempo& bpm, const framepos_t frame, const framepos_t end_frame);
520
521         std::pair<double, framepos_t> predict_tempo_position (TempoSection* section, const Timecode::BBT_Time& bbt);
522         bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt);
523
524         PBD::Signal1<void,const PBD::PropertyChange&> MetricPositionChanged;
525         void fix_legacy_session();
526         void fix_legacy_end_session();
527
528 private:
529         /* prevent copy construction */
530         TempoMap (TempoMap const&);
531
532         TempoSection* previous_tempo_section_locked (const Metrics& metrics, TempoSection*) const;
533         TempoSection* next_tempo_section_locked (const Metrics& metrics, TempoSection*) const;
534
535         double beat_at_minute_locked (const Metrics& metrics, const double& minute) const;
536         double minute_at_beat_locked (const Metrics& metrics, const double& beat) const;
537
538         double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
539         double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
540
541         double pulse_at_minute_locked (const Metrics& metrics, const double& minute) const;
542         double minute_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
543
544         Tempo tempo_at_minute_locked (const Metrics& metrics, const double& minute) const;
545         double minute_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
546
547         Tempo tempo_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
548         double pulse_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const;
549
550         Timecode::BBT_Time bbt_at_minute_locked (const Metrics& metrics, const double& minute) const;
551         double minute_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
552
553         double beat_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
554         Timecode::BBT_Time bbt_at_beat_locked (const Metrics& metrics, const double& beats) const;
555
556         double pulse_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const;
557         Timecode::BBT_Time bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
558
559         double minutes_between_quarter_notes_locked (const Metrics& metrics, const double start_qn, const double end_qn) const;
560         double quarter_notes_between_frames_locked (const Metrics& metrics, const framecnt_t  start, const framecnt_t end) const;
561
562         const TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute) const;
563         TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute);
564         const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
565
566         const MeterSection& meter_section_at_minute_locked (const Metrics& metrics, double minute) const;
567         const MeterSection& meter_section_at_beat_locked (const Metrics& metrics, const double& beat) const;
568
569         bool check_solved (const Metrics& metrics) const;
570         bool set_active_tempi (const Metrics& metrics, const framepos_t& frame);
571
572         bool solve_map_minute (Metrics& metrics, TempoSection* section, const double& minute);
573         bool solve_map_pulse (Metrics& metrics, TempoSection* section, const double& pulse);
574         bool solve_map_minute (Metrics& metrics, MeterSection* section, const double& minute);
575         bool solve_map_bbt (Metrics& metrics, MeterSection* section, const Timecode::BBT_Time& bbt);
576
577         double exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num) const;
578         double exact_qn_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num) const;
579
580         double minute_at_frame (const framepos_t frame) const;
581         framepos_t frame_at_minute (const double minute) const;
582
583         friend class ::BBTTest;
584         friend class ::FrameposPlusBeatsTest;
585         friend class ::FrameposMinusBeatsTest;
586         friend class ::TempoTest;
587
588         static Tempo    _default_tempo;
589         static Meter    _default_meter;
590
591         Metrics                       _metrics;
592         framecnt_t                    _frame_rate;
593         mutable Glib::Threads::RWLock lock;
594
595         void recompute_tempi (Metrics& metrics);
596         void recompute_meters (Metrics& metrics);
597         void recompute_map (Metrics& metrics, framepos_t end = -1);
598
599         MusicFrame round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
600
601         const MeterSection& first_meter() const;
602         MeterSection&       first_meter();
603         const TempoSection& first_tempo() const;
604         TempoSection&       first_tempo();
605
606         void do_insert (MetricSection* section);
607
608         TempoSection* add_tempo_locked (const Tempo&, double pulse, double minute
609                                , PositionLockStyle pls, bool recompute, bool locked_to_meter = false);
610
611         MeterSection* add_meter_locked (const Meter&, double beat, const Timecode::BBT_Time& where, framepos_t frame, PositionLockStyle pls, bool recompute);
612
613         bool remove_tempo_locked (const TempoSection&);
614         bool remove_meter_locked (const MeterSection&);
615
616         TempoSection* copy_metrics_and_point (const Metrics& metrics, Metrics& copy, TempoSection* section) const;
617         MeterSection* copy_metrics_and_point (const Metrics& metrics, Metrics& copy, MeterSection* section) const;
618 };
619
620 }; /* namespace ARDOUR */
621
622 LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
623 LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
624 LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
625
626 namespace PBD {
627         DEFINE_ENUM_CONVERT (ARDOUR::TempoSection::Type)
628 }
629
630 #endif /* __ardour_tempo_h__ */