ardour
tempo.h
Go to the documentation of this file.
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/stateful.h"
32 
33 #include "evoral/types.hpp"
34 
35 #include "ardour/ardour.h"
36 
37 class BBTTest;
39 class TempoTest;
40 class XMLNode;
41 
42 namespace ARDOUR {
43 
44 class Meter;
45 class TempoMap;
46 
49  public:
50  Tempo (double bpm, double type=4.0) // defaulting to quarter note
51  : _beats_per_minute (bpm), _note_type(type) {}
52 
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 {
56  return (60.0 * sr) / _beats_per_minute;
57  }
58 
59  protected:
61  double _note_type;
62 };
63 
66  public:
67  Meter (double dpb, double bt)
68  : _divisions_per_bar (dpb), _note_type (bt) {}
69 
70  double divisions_per_bar () const { return _divisions_per_bar; }
71  double note_divisor() const { return _note_type; }
72 
73  double frames_per_bar (const Tempo&, framecnt_t sr) const;
74  double frames_per_grid (const Tempo&, framecnt_t sr) const;
75 
76  protected:
82 
86  double _note_type;
87 };
88 
91  public:
92  MetricSection (const Timecode::BBT_Time& start)
93  : _start (start), _frame (0), _movable (true) {}
95  : _frame (start), _movable (true) {}
96 
97  virtual ~MetricSection() {}
98 
99  const Timecode::BBT_Time& start() const { return _start; }
100  framepos_t frame() const { return _frame; }
101 
102  void set_movable (bool yn) { _movable = yn; }
103  bool movable() const { return _movable; }
104 
105  virtual void set_frame (framepos_t f) {
106  _frame = f;
107  }
108 
109  virtual void set_start (const Timecode::BBT_Time& w) {
110  _start = w;
111  }
112 
113  /* MeterSections are not stateful in the full sense,
114  but we do want them to control their own
115  XML state information.
116  */
117  virtual XMLNode& get_state() const = 0;
118 
119  private:
120  Timecode::BBT_Time _start;
122  bool _movable;
123 };
124 
127  public:
128  MeterSection (const Timecode::BBT_Time& start, double bpb, double note_type)
129  : MetricSection (start), Meter (bpb, note_type) {}
130  MeterSection (framepos_t start, double bpb, double note_type)
131  : MetricSection (start), Meter (bpb, note_type) {}
132  MeterSection (const XMLNode&);
133 
134  static const std::string xml_state_node_name;
135 
136  XMLNode& get_state() const;
137 };
138 
141  public:
142  TempoSection (const Timecode::BBT_Time& start, double qpm, double note_type)
143  : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
144  TempoSection (framepos_t start, double qpm, double note_type)
145  : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0) {}
146  TempoSection (const XMLNode&);
147 
148  static const std::string xml_state_node_name;
149 
150  XMLNode& get_state() const;
151 
152  void update_bar_offset_from_bbt (const Meter&);
153  void update_bbt_time_from_bar_offset (const Meter&);
154  double bar_offset() const { return _bar_offset; }
155 
156  private:
157  /* this value provides a fractional offset into the bar in which
158  the tempo section is located in. A value of 0.0 indicates that
159  it occurs on the first beat of the bar, a value of 0.5 indicates
160  that it occurs halfway through the bar and so on.
161 
162  this enables us to keep the tempo change at the same relative
163  position within the bar if/when the meter changes.
164  */
165  double _bar_offset;
166 };
167 
168 typedef std::list<MetricSection*> Metrics;
169 
174  public:
175  TempoMetric (const Meter& m, const Tempo& t)
176  : _meter (&m), _tempo (&t), _frame (0) {}
177 
178  void set_tempo (const Tempo& t) { _tempo = &t; }
179  void set_meter (const Meter& m) { _meter = &m; }
180  void set_frame (framepos_t f) { _frame = f; }
181  void set_start (const Timecode::BBT_Time& t) { _start = t; }
182 
183  void set_metric (const MetricSection* section) {
184  const MeterSection* meter;
185  const TempoSection* tempo;
186  if ((meter = dynamic_cast<const MeterSection*>(section))) {
187  set_meter(*meter);
188  } else if ((tempo = dynamic_cast<const TempoSection*>(section))) {
189  set_tempo(*tempo);
190  }
191 
192  set_frame(section->frame());
193  set_start(section->start());
194  }
195 
196  const Meter& meter() const { return *_meter; }
197  const Tempo& tempo() const { return *_tempo; }
198  framepos_t frame() const { return _frame; }
199  const Timecode::BBT_Time& start() const { return _start; }
200 
201  private:
202  const Meter* _meter;
203  const Tempo* _tempo;
205  Timecode::BBT_Time _start;
206 };
207 
209 {
210  public:
211  TempoMap (framecnt_t frame_rate);
212  ~TempoMap();
213 
214  /* measure-based stuff */
215 
219  };
220 
221  struct BBTPoint {
225  uint32_t bar;
226  uint32_t beat;
227 
229  uint32_t b, uint32_t e)
230  : frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
231 
232  Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
233  operator Timecode::BBT_Time() const { return bbt(); }
234  operator framepos_t() const { return frame; }
235  bool is_bar() const { return beat == 1; }
236  };
237 
238  typedef std::vector<BBTPoint> BBTPointList;
239 
240  template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
241  Glib::Threads::RWLock::ReaderLock lm (lock);
242  (obj.*method)(metrics);
243  }
244 
245  void get_grid (BBTPointList::const_iterator&, BBTPointList::const_iterator&,
247 
248  /* TEMPO- AND METER-SENSITIVE FUNCTIONS
249 
250  bbt_time(), bbt_time_rt(), frame_time() and bbt_duration_at()
251  are all sensitive to tempo and meter, and will give answers
252  that align with the grid formed by tempo and meter sections.
253 
254  They SHOULD NOT be used to determine the position of events
255  whose location is canonically defined in beats.
256  */
257 
258  void bbt_time (framepos_t when, Timecode::BBT_Time&);
259 
260  /* realtime safe variant of ::bbt_time(), will throw
261  std::logic_error if the map is not large enough
262  to provide an answer.
263  */
264  void bbt_time_rt (framepos_t when, Timecode::BBT_Time&);
265  framepos_t frame_time (const Timecode::BBT_Time&);
266  framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
267 
268  /* TEMPO-SENSITIVE FUNCTIONS
269 
270  These next 4 functions will all take tempo in account and should be
271  used to determine position (and in the last case, distance in beats)
272  when tempo matters but meter does not.
273 
274  They SHOULD be used to determine the position of events
275  whose location is canonically defined in beats.
276  */
277 
278  framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
279  framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const;
280  framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const;
281  Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const;
282 
283  static const Tempo& default_tempo() { return _default_tempo; }
284  static const Meter& default_meter() { return _default_meter; }
285 
286  const Tempo& tempo_at (framepos_t) const;
287  const Meter& meter_at (framepos_t) const;
288 
289  const TempoSection& tempo_section_at (framepos_t) const;
290  const MeterSection& meter_section_at (framepos_t) const;
291 
292  void add_tempo (const Tempo&, Timecode::BBT_Time where);
293  void add_meter (const Meter&, Timecode::BBT_Time where);
294 
295  void remove_tempo (const TempoSection&, bool send_signal);
296  void remove_meter (const MeterSection&, bool send_signal);
297 
298  void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where);
299  void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
300 
301  framepos_t round_to_bar (framepos_t frame, RoundMode dir);
302  framepos_t round_to_beat (framepos_t frame, RoundMode dir);
303  framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
304 
305  void set_length (framepos_t frames);
306 
307  XMLNode& get_state (void);
308  int set_state (const XMLNode&, int version);
309 
310  void dump (std::ostream&) const;
311  void clear ();
312 
313  TempoMetric metric_at (Timecode::BBT_Time bbt) const;
314 
318  TempoMetric metric_at (framepos_t, Metrics::const_iterator* last=NULL) const;
319 
320  Metrics::const_iterator metrics_end() { return metrics.end(); }
321 
322  void change_existing_tempo_at (framepos_t, double bpm, double note_type);
323  void change_initial_tempo (double bpm, double note_type);
324 
325  void insert_time (framepos_t, framecnt_t);
326  bool cut_time (framepos_t where, framecnt_t amount); //returns true if anything was moved
327 
328  int n_tempos () const;
329  int n_meters () const;
330 
331  framecnt_t frame_rate () const { return _frame_rate; }
332 
333  private:
334 
335  friend class ::BBTTest;
336  friend class ::FrameposPlusBeatsTest;
337  friend class ::TempoTest;
338 
341 
342  Metrics metrics;
344  mutable Glib::Threads::RWLock lock;
345  BBTPointList _map;
346 
347  void recompute_map (bool reassign_tempo_bbt, framepos_t end = -1);
348  void extend_map (framepos_t end);
349  void require_map_to (framepos_t pos);
350  void require_map_to (const Timecode::BBT_Time&);
351  void _extend_map (TempoSection* tempo, MeterSection* meter,
352  Metrics::iterator next_metric,
353  Timecode::BBT_Time current, framepos_t current_frame, framepos_t end);
354 
355  BBTPointList::const_iterator bbt_before_or_at (framepos_t);
356  BBTPointList::const_iterator bbt_before_or_at (const Timecode::BBT_Time&);
357  BBTPointList::const_iterator bbt_after_or_at (framepos_t);
358 
359  framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
360  void bbt_time (framepos_t, Timecode::BBT_Time&, const BBTPointList::const_iterator&);
361  framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
362 
363  const MeterSection& first_meter() const;
364  MeterSection& first_meter();
365  const TempoSection& first_tempo() const;
366  TempoSection& first_tempo();
367 
368  void do_insert (MetricSection* section);
369 
370  void add_tempo_locked (const Tempo&, Timecode::BBT_Time where, bool recompute);
371  void add_meter_locked (const Meter&, Timecode::BBT_Time where, bool recompute);
372 
373  bool remove_tempo_locked (const TempoSection&);
374  bool remove_meter_locked (const MeterSection&);
375 
376 };
377 
378 }; /* namespace ARDOUR */
379 
380 std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
381 std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
382 std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
383 
384 #endif /* __ardour_tempo_h__ */
const Timecode::BBT_Time & start() const
Definition: tempo.h:199
static Meter _default_meter
Definition: tempo.h:340
Glib::Threads::RWLock lock
Definition: tempo.h:344
std::ostream & operator<<(std::ostream &, const ARDOUR::Meter &)
Definition: tempo.cc:2468
framecnt_t frame_rate() const
Definition: tempo.h:331
RoundMode
Definition: types.h:221
const Meter & meter() const
Definition: tempo.h:196
bool is_bar() const
Definition: tempo.h:235
std::list< MetricSection * > Metrics
Definition: tempo.h:168
virtual ~MetricSection()
Definition: tempo.h:97
void set_metric(const MetricSection *section)
Definition: tempo.h:183
Meter(double dpb, double bt)
Definition: tempo.h:67
void set_meter(const Meter &m)
Definition: tempo.h:179
Metrics::const_iterator metrics_end()
Definition: tempo.h:320
TempoSection(framepos_t start, double qpm, double note_type)
Definition: tempo.h:144
tuple f
Definition: signals.py:35
double bar_offset() const
Definition: tempo.h:154
bool movable() const
Definition: tempo.h:103
BBTPointList _map
Definition: tempo.h:345
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
double _bar_offset
Definition: tempo.h:165
framepos_t frame() const
Definition: tempo.h:198
double _divisions_per_bar
Definition: tempo.h:81
MeterSection(const Timecode::BBT_Time &start, double bpb, double note_type)
Definition: tempo.h:128
framepos_t _frame
Definition: tempo.h:204
Timecode::BBT_Time _start
Definition: tempo.h:205
LIBARDOUR_API uint64_t TempoMap
Definition: debug.cc:60
const Timecode::BBT_Time & start() const
Definition: tempo.h:99
double frames_per_beat(framecnt_t sr) const
Definition: tempo.h:55
void set_start(const Timecode::BBT_Time &t)
Definition: tempo.h:181
framecnt_t _frame_rate
Definition: tempo.h:343
MetricSection(framepos_t start)
Definition: tempo.h:94
int64_t framecnt_t
Definition: types.h:76
Tempo(double bpm, double type=4.0)
Definition: tempo.h:50
static const std::string xml_state_node_name
Definition: tempo.h:148
Timecode::BBT_Time bbt() const
Definition: tempo.h:232
static const Meter & default_meter()
Definition: tempo.h:284
virtual void set_start(const Timecode::BBT_Time &w)
Definition: tempo.h:109
Definition: amp.h:29
double _note_type
Definition: tempo.h:86
const Meter * _meter
Definition: tempo.h:202
static int add_tempo(smf_t *smf, int pulses, int tempo)
Definition: smf_tempo.c:95
BBTPoint(const MeterSection &m, const TempoSection &t, framepos_t f, uint32_t b, uint32_t e)
Definition: tempo.h:228
int64_t framepos_t
Definition: types.h:66
double note_divisor() const
Definition: tempo.h:71
double beats_per_minute() const
Definition: tempo.h:53
#define LIBARDOUR_API
virtual void set_frame(framepos_t f)
Definition: tempo.h:105
const TempoSection * tempo
Definition: tempo.h:224
const Tempo * _tempo
Definition: tempo.h:203
void set_tempo(const Tempo &t)
Definition: tempo.h:178
void set_frame(framepos_t f)
Definition: tempo.h:180
Definition: xml++.h:95
const Tempo & tempo() const
Definition: tempo.h:197
double divisions_per_bar() const
Definition: tempo.h:70
framepos_t frame() const
Definition: tempo.h:100
TempoSection(const Timecode::BBT_Time &start, double qpm, double note_type)
Definition: tempo.h:142
TempoMetric(const Meter &m, const Tempo &t)
Definition: tempo.h:175
double _beats_per_minute
Definition: tempo.h:60
MeterSection(framepos_t start, double bpb, double note_type)
Definition: tempo.h:130
MetricSection(const Timecode::BBT_Time &start)
Definition: tempo.h:92
framepos_t _frame
Definition: tempo.h:121
double note_type() const
Definition: tempo.h:54
void apply_with_metrics(T &obj, void(T::*method)(const Metrics &))
Definition: tempo.h:240
void set_movable(bool yn)
Definition: tempo.h:102
const MeterSection * meter
Definition: tempo.h:223
std::vector< BBTPoint > BBTPointList
Definition: tempo.h:238
static Tempo _default_tempo
Definition: tempo.h:339
static const Tempo & default_tempo()
Definition: tempo.h:283
Timecode::BBT_Time _start
Definition: tempo.h:120
Metrics metrics
Definition: tempo.h:342
static const std::string xml_state_node_name
Definition: tempo.h:134
double _note_type
Definition: tempo.h:61