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