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"
47 Tempo (double bpm, double type=4.0) // defaulting to quarter note
48 : _beats_per_minute (bpm), _note_type(type) {}
50 double beats_per_minute () const { return _beats_per_minute;}
51 double note_type () const { return _note_type;}
52 double frames_per_beat (framecnt_t sr) const;
55 double _beats_per_minute;
61 Meter (double dpb, double bt)
62 : _divisions_per_bar (dpb), _note_type (bt) {}
64 double divisions_per_bar () const { return _divisions_per_bar; }
65 double note_divisor() const { return _note_type; }
67 double frames_per_bar (const Tempo&, framecnt_t sr) const;
68 double frames_per_division (const Tempo&, framecnt_t sr) const;
71 /** The number of divisions in a bar. This is a floating point value because
72 there are musical traditions on our planet that do not limit
73 themselves to integral numbers of beats per bar.
75 double _divisions_per_bar;
77 /** The type of "note" that a division represents. For example, 4.0 is
78 a quarter (crotchet) note, 8.0 is an eighth (quaver) note, etc.
85 MetricSection (const Timecode::BBT_Time& start)
86 : _start (start), _frame (0), _movable (true) {}
87 MetricSection (framepos_t start)
88 : _frame (start), _movable (true) {}
90 virtual ~MetricSection() {}
92 const Timecode::BBT_Time& start() const { return _start; }
93 framepos_t frame() const { return _frame; }
95 void set_movable (bool yn) { _movable = yn; }
96 bool movable() const { return _movable; }
98 virtual void set_frame (framepos_t f) {
102 virtual void set_start (const Timecode::BBT_Time& w) {
106 /* MeterSections are not stateful in the full sense,
107 but we do want them to control their own
108 XML state information.
110 virtual XMLNode& get_state() const = 0;
112 int compare (const MetricSection&) const;
113 bool operator== (const MetricSection& other) const;
114 bool operator!= (const MetricSection& other) const;
117 Timecode::BBT_Time _start;
122 class MeterSection : public MetricSection, public Meter {
124 MeterSection (const Timecode::BBT_Time& start, double bpb, double note_type)
125 : MetricSection (start), Meter (bpb, note_type) {}
126 MeterSection (framepos_t start, double bpb, double note_type)
127 : MetricSection (start), Meter (bpb, note_type) {}
128 MeterSection (const XMLNode&);
130 static const std::string xml_state_node_name;
132 XMLNode& get_state() const;
135 class TempoSection : public MetricSection, public Tempo {
137 TempoSection (const Timecode::BBT_Time& start, double qpm, double note_type)
138 : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
139 TempoSection (framepos_t start, double qpm, double note_type)
140 : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
141 TempoSection (const XMLNode&);
143 static const std::string xml_state_node_name;
145 XMLNode& get_state() const;
147 void update_bar_offset_from_bbt (const Meter&);
148 void update_bbt_time_from_bar_offset (const Meter&);
149 double bar_offset() const { return _bar_offset; }
152 /* this value provides a fractional offset into the bar in which
153 the tempo section is located in. A value of 0.0 indicates that
154 it occurs on the first beat of the bar, a value of 0.5 indicates
155 that it occurs halfway through the bar and so on.
157 this enables us to keep the tempo change at the same relative
158 position within the bar if/when the meter changes.
163 typedef std::list<MetricSection*> Metrics;
165 /** Helper class that we use to be able to keep track of which
166 meter *AND* tempo are in effect at a given point in time.
170 TempoMetric (const Meter& m, const Tempo& t) : _meter (&m), _tempo (&t), _frame (0) {}
172 void set_tempo (const Tempo& t) { _tempo = &t; }
173 void set_meter (const Meter& m) { _meter = &m; }
174 void set_frame (framepos_t f) { _frame = f; }
175 void set_start (const Timecode::BBT_Time& t) { _start = t; }
177 const Meter& meter() const { return *_meter; }
178 const Tempo& tempo() const { return *_tempo; }
179 framepos_t frame() const { return _frame; }
180 const Timecode::BBT_Time& start() const { return _start; }
186 Timecode::BBT_Time _start;
189 class TempoMap : public PBD::StatefulDestructible
192 TempoMap (framecnt_t frame_rate);
195 /* measure-based stuff */
210 Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
211 operator Timecode::BBT_Time() const { return bbt(); }
212 operator framepos_t() const { return frame; }
214 BBTPoint (const Meter& m, const Tempo& t, framepos_t f,
215 BBTPointType ty, uint32_t b, uint32_t e)
216 : type (ty), frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
219 typedef std::vector<BBTPoint> BBTPointList;
221 template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
222 Glib::RWLock::ReaderLock lm (lock);
223 (obj.*method)(*metrics);
226 const BBTPointList& map() const { return _map ; }
227 void map (BBTPointList&, framepos_t start, framepos_t end);
229 void bbt_time (framepos_t when, Timecode::BBT_Time&);
230 framecnt_t frame_time (const Timecode::BBT_Time&);
231 framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
233 static const Tempo& default_tempo() { return _default_tempo; }
234 static const Meter& default_meter() { return _default_meter; }
236 const Tempo& tempo_at (framepos_t) const;
237 const Meter& meter_at (framepos_t) const;
239 const TempoSection& tempo_section_at (framepos_t) const;
241 void add_tempo(const Tempo&, Timecode::BBT_Time where);
242 void add_meter(const Meter&, Timecode::BBT_Time where);
244 void remove_tempo(const TempoSection&, bool send_signal);
245 void remove_meter(const MeterSection&, bool send_signal);
247 void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where);
248 void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
250 framepos_t round_to_bar (framepos_t frame, int dir);
251 framepos_t round_to_beat (framepos_t frame, int dir);
252 framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, int dir);
253 framepos_t round_to_tick (framepos_t frame, int dir);
255 void set_length (framepos_t frames);
257 XMLNode& get_state (void);
258 int set_state (const XMLNode&, int version);
260 void dump (std::ostream&) const;
263 TempoMetric metric_at (Timecode::BBT_Time bbt) const;
264 TempoMetric metric_at (framepos_t) const;
266 framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b);
267 framepos_t framepos_plus_beats (framepos_t, Evoral::MusicalTime);
268 framepos_t framepos_minus_beats (framepos_t, Evoral::MusicalTime);
269 Evoral::MusicalTime framewalk_to_beats (framepos_t pos, framecnt_t distance);
271 void change_existing_tempo_at (framepos_t, double bpm, double note_type);
272 void change_initial_tempo (double bpm, double note_type);
274 void insert_time (framepos_t, framecnt_t);
276 int n_tempos () const;
277 int n_meters () const;
279 framecnt_t frame_rate () const { return _frame_rate; }
283 friend class ::BBTTest;
285 static Tempo _default_tempo;
286 static Meter _default_meter;
289 framecnt_t _frame_rate;
290 framepos_t last_bbt_when;
292 Timecode::BBT_Time last_bbt;
293 mutable Glib::RWLock lock;
296 void recompute_map (bool reassign_tempo_bbt, framepos_t end = -1);
297 void require_map_to (framepos_t pos);
298 void require_map_to (const Timecode::BBT_Time&);
300 BBTPointList::const_iterator bbt_before_or_at (framepos_t);
301 BBTPointList::const_iterator bbt_after_or_at (framepos_t);
302 BBTPointList::const_iterator bbt_point_for (const Timecode::BBT_Time&);
304 void timestamp_metrics_from_audio_time ();
306 framepos_t round_to_type (framepos_t fr, int dir, BBTPointType);
308 void bbt_time_unlocked (framepos_t, Timecode::BBT_Time&);
310 framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
312 const MeterSection& first_meter() const;
313 const TempoSection& first_tempo() const;
315 int move_metric_section (MetricSection&, const Timecode::BBT_Time& to);
316 void do_insert (MetricSection* section);
318 Timecode::BBT_Time bbt_add (const Timecode::BBT_Time&, const Timecode::BBT_Time&, const TempoMetric&) const;
319 Timecode::BBT_Time bbt_add (const Timecode::BBT_Time& a, const Timecode::BBT_Time& b) const;
320 Timecode::BBT_Time bbt_subtract (const Timecode::BBT_Time&, const Timecode::BBT_Time&) const;
323 }; /* namespace ARDOUR */
325 std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
326 std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
327 std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
329 #endif /* __ardour_tempo_h__ */