2 Copyright (C) 2000 Paul Davis
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.
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.
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.
20 #ifndef __ardour_tempo_h__
21 #define __ardour_tempo_h__
27 #include <glibmm/thread.h>
30 #include "pbd/stateful.h"
31 #include "pbd/statefuldestructible.h"
33 #include "evoral/types.hpp"
35 #include "ardour/ardour.h"
40 class FrameposPlusBeatsTest;
50 Tempo (double bpm, double type=4.0) // defaulting to quarter note
51 : _beats_per_minute (bpm), _note_type(type) {}
53 double beats_per_minute () const { return _beats_per_minute;}
54 double note_type () const { return _note_type;}
55 double frames_per_beat (framecnt_t sr) const;
58 double _beats_per_minute;
64 Meter (double dpb, double bt)
65 : _divisions_per_bar (dpb), _note_type (bt) {}
67 double divisions_per_bar () const { return _divisions_per_bar; }
68 double note_divisor() const { return _note_type; }
70 double frames_per_bar (const Tempo&, framecnt_t sr) const;
71 double frames_per_division (const Tempo&, framecnt_t sr) const;
74 /** The number of divisions in a bar. This is a floating point value because
75 there are musical traditions on our planet that do not limit
76 themselves to integral numbers of beats per bar.
78 double _divisions_per_bar;
80 /** The type of "note" that a division represents. For example, 4.0 is
81 a quarter (crotchet) note, 8.0 is an eighth (quaver) note, etc.
88 MetricSection (const Timecode::BBT_Time& start)
89 : _start (start), _frame (0), _movable (true) {}
90 MetricSection (framepos_t start)
91 : _frame (start), _movable (true) {}
93 virtual ~MetricSection() {}
95 const Timecode::BBT_Time& start() const { return _start; }
96 framepos_t frame() const { return _frame; }
98 void set_movable (bool yn) { _movable = yn; }
99 bool movable() const { return _movable; }
101 virtual void set_frame (framepos_t f) {
105 virtual void set_start (const Timecode::BBT_Time& w) {
109 /* MeterSections are not stateful in the full sense,
110 but we do want them to control their own
111 XML state information.
113 virtual XMLNode& get_state() const = 0;
115 int compare (const MetricSection&) const;
116 bool operator== (const MetricSection& other) const;
117 bool operator!= (const MetricSection& other) const;
120 Timecode::BBT_Time _start;
125 class MeterSection : public MetricSection, public Meter {
127 MeterSection (const Timecode::BBT_Time& start, double bpb, double note_type)
128 : MetricSection (start), Meter (bpb, note_type) {}
129 MeterSection (framepos_t start, double bpb, double note_type)
130 : MetricSection (start), Meter (bpb, note_type) {}
131 MeterSection (const XMLNode&);
133 static const std::string xml_state_node_name;
135 XMLNode& get_state() const;
138 class TempoSection : public MetricSection, public Tempo {
140 TempoSection (const Timecode::BBT_Time& start, double qpm, double note_type)
141 : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
142 TempoSection (framepos_t start, double qpm, double note_type)
143 : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
144 TempoSection (const XMLNode&);
146 static const std::string xml_state_node_name;
148 XMLNode& get_state() const;
150 void update_bar_offset_from_bbt (const Meter&);
151 void update_bbt_time_from_bar_offset (const Meter&);
152 double bar_offset() const { return _bar_offset; }
155 /* this value provides a fractional offset into the bar in which
156 the tempo section is located in. A value of 0.0 indicates that
157 it occurs on the first beat of the bar, a value of 0.5 indicates
158 that it occurs halfway through the bar and so on.
160 this enables us to keep the tempo change at the same relative
161 position within the bar if/when the meter changes.
166 typedef std::list<MetricSection*> Metrics;
168 /** Helper class that we use to be able to keep track of which
169 meter *AND* tempo are in effect at a given point in time.
173 TempoMetric (const Meter& m, const Tempo& t) : _meter (&m), _tempo (&t), _frame (0) {}
175 void set_tempo (const Tempo& t) { _tempo = &t; }
176 void set_meter (const Meter& m) { _meter = &m; }
177 void set_frame (framepos_t f) { _frame = f; }
178 void set_start (const Timecode::BBT_Time& t) { _start = t; }
180 const Meter& meter() const { return *_meter; }
181 const Tempo& tempo() const { return *_tempo; }
182 framepos_t frame() const { return _frame; }
183 const Timecode::BBT_Time& start() const { return _start; }
189 Timecode::BBT_Time _start;
192 class TempoMap : public PBD::StatefulDestructible
195 TempoMap (framecnt_t frame_rate);
198 /* measure-based stuff */
212 Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
213 operator Timecode::BBT_Time() const { return bbt(); }
214 operator framepos_t() const { return frame; }
216 bool is_bar() const { return beat == 1; }
218 BBTPoint (const Meter& m, const Tempo& t, framepos_t f,
219 uint32_t b, uint32_t e)
220 : frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
223 typedef std::vector<BBTPoint> BBTPointList;
225 template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
226 Glib::RWLock::ReaderLock lm (metrics_lock);
227 (obj.*method)(*metrics);
230 void map (BBTPointList::const_iterator&, BBTPointList::const_iterator&,
231 framepos_t start, framepos_t end);
233 void bbt_time (framepos_t when, Timecode::BBT_Time&);
234 framecnt_t frame_time (const Timecode::BBT_Time&);
235 framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
237 static const Tempo& default_tempo() { return _default_tempo; }
238 static const Meter& default_meter() { return _default_meter; }
240 const Tempo& tempo_at (framepos_t) const;
241 const Meter& meter_at (framepos_t) const;
243 const TempoSection& tempo_section_at (framepos_t) const;
245 void add_tempo(const Tempo&, Timecode::BBT_Time where);
246 void add_meter(const Meter&, Timecode::BBT_Time where);
248 void remove_tempo(const TempoSection&, bool send_signal);
249 void remove_meter(const MeterSection&, bool send_signal);
251 void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where);
252 void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
254 framepos_t round_to_bar (framepos_t frame, int dir);
255 framepos_t round_to_beat (framepos_t frame, int dir);
256 framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, int dir);
257 framepos_t round_to_tick (framepos_t frame, int dir);
259 void set_length (framepos_t frames);
261 XMLNode& get_state (void);
262 int set_state (const XMLNode&, int version);
264 void dump (std::ostream&) const;
267 TempoMetric metric_at (Timecode::BBT_Time bbt) const;
268 TempoMetric metric_at (framepos_t) const;
270 framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b);
271 framepos_t framepos_plus_beats (framepos_t, Evoral::MusicalTime);
272 framepos_t framepos_minus_bbt (framepos_t pos, Timecode::BBT_Time b);
273 framepos_t framepos_minus_beats (framepos_t, Evoral::MusicalTime);
274 Evoral::MusicalTime framewalk_to_beats (framepos_t pos, framecnt_t distance);
276 void change_existing_tempo_at (framepos_t, double bpm, double note_type);
277 void change_initial_tempo (double bpm, double note_type);
279 void insert_time (framepos_t, framecnt_t);
281 int n_tempos () const;
282 int n_meters () const;
284 framecnt_t frame_rate () const { return _frame_rate; }
288 friend class ::BBTTest;
289 friend class ::FrameposPlusBeatsTest;
290 friend class ::TempoTest;
292 static Tempo _default_tempo;
293 static Meter _default_meter;
296 framecnt_t _frame_rate;
297 framepos_t last_bbt_when;
299 Timecode::BBT_Time last_bbt;
300 mutable Glib::RWLock metrics_lock;
301 mutable Glib::RWLock map_lock;
304 void recompute_map (bool reassign_tempo_bbt, framepos_t end = -1);
305 void require_map_to (framepos_t pos);
306 void require_map_to (const Timecode::BBT_Time&);
308 BBTPointList::const_iterator bbt_before_or_at (framepos_t);
309 BBTPointList::const_iterator bbt_after_or_at (framepos_t);
310 BBTPointList::const_iterator bbt_point_for (const Timecode::BBT_Time&);
312 void timestamp_metrics_from_audio_time ();
314 framepos_t round_to_type (framepos_t fr, int dir, BBTPointType);
316 void bbt_time_unlocked (framepos_t, Timecode::BBT_Time&, const BBTPointList::const_iterator&);
318 framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
320 const MeterSection& first_meter() const;
321 const TempoSection& first_tempo() const;
323 int move_metric_section (MetricSection&, const Timecode::BBT_Time& to);
324 void do_insert (MetricSection* section);
326 Timecode::BBT_Time bbt_add (const Timecode::BBT_Time&, const Timecode::BBT_Time&, const TempoMetric&) const;
327 Timecode::BBT_Time bbt_add (const Timecode::BBT_Time& a, const Timecode::BBT_Time& b) const;
328 Timecode::BBT_Time bbt_subtract (const Timecode::BBT_Time&, const Timecode::BBT_Time&) const;
331 }; /* namespace ARDOUR */
333 std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
334 std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
335 std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
337 #endif /* __ardour_tempo_h__ */