Tempo ramps - music-locked meters now use beats rather than pulses as their reference.
[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
31 #include "pbd/stateful.h"
32 #include "pbd/statefuldestructible.h"
33
34 #include "evoral/Beats.hpp"
35
36 #include "ardour/ardour.h"
37
38 class BBTTest;
39 class FrameposPlusBeatsTest;
40 class TempoTest;
41 class XMLNode;
42
43 namespace ARDOUR {
44
45 class Meter;
46 class TempoMap;
47
48 /** Tempo, the speed at which musical time progresses (BPM). */
49 class LIBARDOUR_API Tempo {
50   public:
51         /**
52          * @param bpm Beats Per Minute
53          * @param type Note Type (default `4': quarter note)
54          */
55         Tempo (double bpm, double type=4.0) // defaulting to quarter note
56                 : _beats_per_minute (bpm), _note_type(type) {}
57
58         double beats_per_minute () const { return _beats_per_minute; }
59         double note_type () const { return _note_type; }
60         double pulses_per_minute () const { return _beats_per_minute / _note_type; }
61         /** audio samples per beat
62          * @param sr samplerate
63          */
64         double frames_per_beat (framecnt_t sr) const {
65                 return (60.0 * sr) / _beats_per_minute;
66         }
67         double frames_per_pulse (framecnt_t sr) const {
68                 return (_note_type * 60.0 * sr) / _beats_per_minute;
69         }
70
71   protected:
72         double _beats_per_minute;
73         double _note_type;
74 };
75
76 /** Meter, or time signature (beats per bar, and which note type is a beat). */
77 class LIBARDOUR_API Meter {
78   public:
79         Meter (double dpb, double bt)
80                 : _divisions_per_bar (dpb), _note_type (bt) {}
81
82         double divisions_per_bar () const { return _divisions_per_bar; }
83         double note_divisor() const { return _note_type; }
84
85         double frames_per_bar (const Tempo&, framecnt_t sr) const;
86         double frames_per_grid (const Tempo&, framecnt_t sr) const;
87
88   protected:
89         /** The number of divisions in a bar.  This is a floating point value because
90             there are musical traditions on our planet that do not limit
91             themselves to integral numbers of beats per bar.
92         */
93         double _divisions_per_bar;
94
95         /** The type of "note" that a division represents.  For example, 4.0 is
96             a quarter (crotchet) note, 8.0 is an eighth (quaver) note, etc.
97         */
98         double _note_type;
99 };
100
101 /** A section of timeline with a certain Tempo or Meter. */
102 class LIBARDOUR_API MetricSection {
103   public:
104         MetricSection (double pulse)
105                 : _pulse (pulse), _frame (0), _movable (true), _position_lock_style (PositionLockStyle::MusicTime) {}
106         MetricSection (framepos_t frame)
107                 : _pulse (0.0), _frame (frame), _movable (true), _position_lock_style (PositionLockStyle::AudioTime) {}
108
109         virtual ~MetricSection() {}
110
111         const double& pulse () const { return _pulse; }
112         void set_pulse (double pulse) { _pulse = pulse; }
113
114         framepos_t frame() const { return _frame; }
115         virtual void set_frame (framepos_t f) {
116                 _frame = f;
117         }
118
119         void set_movable (bool yn) { _movable = yn; }
120         bool movable() const { return _movable; }
121
122         /* MeterSections are not stateful in the full sense,
123            but we do want them to control their own
124            XML state information.
125         */
126         virtual XMLNode& get_state() const = 0;
127
128         PositionLockStyle position_lock_style () const { return _position_lock_style; }
129         void set_position_lock_style (PositionLockStyle ps) { _position_lock_style = ps; }
130
131 private:
132         double             _pulse;
133         framepos_t         _frame;
134         bool               _movable;
135         PositionLockStyle  _position_lock_style;
136 };
137
138 /** A section of timeline with a certain Meter. */
139 class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
140   public:
141         MeterSection (double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type)
142                 : MetricSection (beat), Meter (bpb, note_type), _bbt (bbt) {}
143         MeterSection (framepos_t frame, double bpb, double note_type)
144                 : MetricSection (frame), Meter (bpb, note_type), _bbt (1, 1, 0) {}
145         MeterSection (const XMLNode&);
146
147         static const std::string xml_state_node_name;
148
149         XMLNode& get_state() const;
150
151         void set_pulse (std::pair<double, Timecode::BBT_Time>& w) {
152                 MetricSection::set_pulse (w.first);
153                 _bbt = w.second;
154         }
155
156         const Timecode::BBT_Time& bbt() const { return _bbt; }
157         const double& beat () const { return _beat; }
158         void set_beat (double beat) { _beat = beat; }
159
160 private:
161         Timecode::BBT_Time _bbt;
162         double _beat;
163 };
164
165 /** A section of timeline with a certain Tempo. */
166 class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
167   public:
168         enum Type {
169                 Ramp,
170                 Constant,
171         };
172
173         TempoSection (const double& beat, double qpm, double note_type, Type tempo_type)
174                 : MetricSection (beat), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type), _c_func (0.0)  {}
175         TempoSection (framepos_t frame, double qpm, double note_type, Type tempo_type)
176                 : MetricSection (frame), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type), _c_func (0.0) {}
177         TempoSection (const XMLNode&);
178
179         static const std::string xml_state_node_name;
180
181         XMLNode& get_state() const;
182
183         void update_bar_offset_from_bbt (const Meter&);
184         void update_bbt_time_from_bar_offset (const Meter&);
185         double bar_offset() const { return _bar_offset; }
186
187         void set_type (Type type);
188         Type type () const { return _type; }
189
190         double tempo_at_frame (const framepos_t& frame, const framecnt_t& frame_rate) const;
191         framepos_t frame_at_tempo (const double& ppm, const double& beat, const framecnt_t& frame_rate) const;
192
193         double tempo_at_pulse (const double& pulse) const;
194         double pulse_at_tempo (const double& ppm, const framepos_t& frame, const framecnt_t& frame_rate) const;
195
196         double pulse_at_frame (const framepos_t& frame, const framecnt_t& frame_rate) const;
197         framepos_t frame_at_pulse (const double& pulse, const framecnt_t& frame_rate) const;
198
199         double compute_c_func_pulse (const double& end_bpm, const double& end_pulse, const framecnt_t& frame_rate);
200         double compute_c_func_frame (const double& end_bpm, const framepos_t& end_frame, const framecnt_t& frame_rate) const;
201
202         double get_c_func () const { return _c_func; }
203         void set_c_func (double c_func) { _c_func = c_func; }
204
205         Timecode::BBT_Time legacy_bbt () { return _legacy_bbt; }
206
207   private:
208
209         framecnt_t minute_to_frame (const double& time, const framecnt_t& frame_rate) const;
210         double frame_to_minute (const framecnt_t& frame, const framecnt_t& frame_rate) const;
211
212         /*  tempo ramp functions. zero-based with time in minutes,
213          * 'tick tempo' in ticks per minute and tempo in bpm.
214          *  time relative to section start.
215          */
216         double a_func (double end_tpm, double c_func) const;
217         double c_func (double end_tpm, double end_time) const;
218
219         double pulse_tempo_at_time (const double& time) const;
220         double time_at_pulse_tempo (const double& pulse_tempo) const;
221
222         double pulse_tempo_at_pulse (const double& pulse) const;
223         double pulse_at_pulse_tempo (const double& pulse_tempo) const;
224
225         double pulse_at_time (const double& time) const;
226         double time_at_pulse (const double& pulse) const;
227
228         /* this value provides a fractional offset into the bar in which
229            the tempo section is located in. A value of 0.0 indicates that
230            it occurs on the first beat of the bar, a value of 0.5 indicates
231            that it occurs halfway through the bar and so on.
232
233            this enables us to keep the tempo change at the same relative
234            position within the bar if/when the meter changes.
235         */
236         double _bar_offset;
237         Type _type;
238         double _c_func;
239         Timecode::BBT_Time _legacy_bbt;
240 };
241
242 typedef std::list<MetricSection*> Metrics;
243
244 /** Helper class to keep track of the Meter *AND* Tempo in effect
245     at a given point in time.
246 */
247 class LIBARDOUR_API TempoMetric {
248   public:
249         TempoMetric (const Meter& m, const Tempo& t)
250                 : _meter (&m), _tempo (&t), _frame (0) {}
251
252         void set_tempo (const Tempo& t)              { _tempo = &t; }
253         void set_meter (const Meter& m)              { _meter = &m; }
254         void set_frame (framepos_t f)                { _frame = f; }
255         void set_pulse (const double& p)             { _pulse = p; }
256
257         void set_metric (const MetricSection* section) {
258                 const MeterSection* meter;
259                 const TempoSection* tempo;
260                 if ((meter = dynamic_cast<const MeterSection*>(section))) {
261                         set_meter(*meter);
262                 } else if ((tempo = dynamic_cast<const TempoSection*>(section))) {
263                         set_tempo(*tempo);
264                 }
265
266                 set_frame (section->frame());
267                 set_pulse (section->pulse());
268         }
269
270         const Meter&              meter() const { return *_meter; }
271         const Tempo&              tempo() const { return *_tempo; }
272         framepos_t                frame() const { return _frame; }
273         const double&             pulse() const { return _pulse; }
274
275   private:
276         const Meter*       _meter;
277         const Tempo*       _tempo;
278         framepos_t         _frame;
279         double             _pulse;
280 };
281
282 /** Tempo Map - mapping of timecode to musical time.
283  * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo
284  */
285 class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
286 {
287   public:
288         TempoMap (framecnt_t frame_rate);
289         ~TempoMap();
290
291         /* measure-based stuff */
292
293         enum BBTPointType {
294                 Bar,
295                 Beat,
296         };
297
298         struct BBTPoint {
299                 framepos_t          frame;
300                 const MeterSection* meter;
301                 const Tempo tempo;
302                 uint32_t            bar;
303                 uint32_t            beat;
304
305                 BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f,
306                           uint32_t b, uint32_t e)
307                 : frame (f), meter (&m), tempo (t.beats_per_minute(), t.note_type()), bar (b), beat (e) {}
308
309                 Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
310                 operator Timecode::BBT_Time() const { return bbt(); }
311                 operator framepos_t() const { return frame; }
312                 bool is_bar() const { return beat == 1; }
313         };
314
315         template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
316                 Glib::Threads::RWLock::ReaderLock lm (lock);
317                 (obj.*method)(_metrics);
318         }
319
320         void get_grid (std::vector<BBTPoint>&,
321                        framepos_t start, framepos_t end);
322
323         /* TEMPO- AND METER-SENSITIVE FUNCTIONS
324
325            bbt_time(), beat_at_frame(), frame_at_beat(), tick_at_frame(),
326            frame_at_tick(),frame_time() and bbt_duration_at()
327            are all sensitive to tempo and meter, and will give answers
328            that align with the grid formed by tempo and meter sections.
329
330            They SHOULD NOT be used to determine the position of events
331            whose location is canonically defined in beats.
332         */
333
334         void bbt_time (framepos_t when, Timecode::BBT_Time&);
335
336         double beat_at_frame (const framecnt_t& frame) const;
337         framecnt_t frame_at_beat (const double& beat) const;
338
339         framepos_t frame_time (const Timecode::BBT_Time&);
340         framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
341
342         /* TEMPO-SENSITIVE FUNCTIONS
343
344            These next 4 functions will all take tempo in account and should be
345            used to determine position (and in the last case, distance in beats)
346            when tempo matters but meter does not.
347
348            They SHOULD be used to determine the position of events
349            whose location is canonically defined in beats.
350         */
351
352         framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
353         framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const;
354         framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const;
355         Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const;
356
357         static const Tempo& default_tempo() { return _default_tempo; }
358         static const Meter& default_meter() { return _default_meter; }
359
360         const Tempo tempo_at (const framepos_t& frame) const;
361         double frames_per_beat_at (const framepos_t&, const framecnt_t& sr) const;
362
363         const Meter& meter_at (framepos_t) const;
364
365         const TempoSection& tempo_section_at (framepos_t frame) const;
366         const MeterSection& meter_section_at (framepos_t frame) const;
367
368         void add_tempo (const Tempo&, const double& pulse, TempoSection::Type type);
369         void add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type);
370
371         void add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where);
372         void add_meter (const Meter&, const framepos_t& frame);
373
374         void remove_tempo (const TempoSection&, bool send_signal);
375         void remove_meter (const MeterSection&, bool send_signal);
376
377         framepos_t predict_tempo_frame (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt);
378         double predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame);
379
380         void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
381         void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& frame, TempoSection::Type type);
382
383         void gui_move_tempo_frame (TempoSection*, const Tempo& bpm, const framepos_t& frame);
384         void gui_move_tempo_beat (TempoSection*, const Tempo& bpm, const double& frame);
385         void gui_move_meter (MeterSection*, const Meter& mt, const framepos_t& frame);
386         void gui_move_meter (MeterSection*, const Meter& mt, const double& beat);
387
388         bool can_solve_bbt (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt);
389
390         void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
391         void replace_meter (const MeterSection&, const Meter&, const framepos_t& frame);
392
393         framepos_t round_to_bar  (framepos_t frame, RoundMode dir);
394         framepos_t round_to_beat (framepos_t frame, RoundMode dir);
395         framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
396
397         void set_length (framepos_t frames);
398
399         XMLNode& get_state (void);
400         int set_state (const XMLNode&, int version);
401
402         void dump (const Metrics& metrics, std::ostream&) const;
403         void clear ();
404
405         TempoMetric metric_at (Timecode::BBT_Time bbt) const;
406
407         /** Return the TempoMetric at frame @p t, and point @p last to the latest
408          * metric change <= t, if it is non-NULL.
409          */
410         TempoMetric metric_at (framepos_t, Metrics::const_iterator* last=NULL) const;
411
412         Metrics::const_iterator metrics_end() { return _metrics.end(); }
413
414         void change_existing_tempo_at (framepos_t, double bpm, double note_type);
415         void change_initial_tempo (double bpm, double note_type);
416
417         void insert_time (framepos_t, framecnt_t);
418         bool remove_time (framepos_t where, framecnt_t amount);  //returns true if anything was moved
419
420         int n_tempos () const;
421         int n_meters () const;
422
423         framecnt_t frame_rate () const { return _frame_rate; }
424
425         double bbt_to_beats (const Timecode::BBT_Time& bbt);
426         Timecode::BBT_Time beats_to_bbt (const double& beats);
427         Timecode::BBT_Time pulse_to_bbt (const double& pulse);
428
429         double pulse_at_beat (const double& beat) const;
430         double beat_at_pulse (const double& pulse) const;
431
432         PBD::Signal0<void> MetricPositionChanged;
433
434 private:
435         double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
436         double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
437         double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
438         framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& beat) const;
439
440         double pulse_offset_at (const Metrics& metrics, const double& pulse) const;
441         frameoffset_t frame_offset_at (const Metrics& metrics, const framepos_t& frame) const;
442
443         double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
444         framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
445         double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
446         Timecode::BBT_Time beats_to_bbt_locked (const Metrics& metrics, const double& beats) const;
447
448         framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
449
450         const MeterSection& meter_section_at_locked (framepos_t frame) const;
451         const TempoSection& tempo_section_at_locked (framepos_t frame) const;
452
453         bool check_solved (Metrics& metrics, bool by_frame);
454         bool solve_map (Metrics& metrics, TempoSection* section, const Tempo& bpm, const framepos_t& frame);
455         bool solve_map (Metrics& metrics, TempoSection* section, const Tempo& bpm, const double& pulse);
456         void solve_map (Metrics& metrics, MeterSection* section, const Meter& mt, const framepos_t& frame);
457         void solve_map (Metrics& metrics, MeterSection* section, const Meter& mt, const double& pulse);
458
459         friend class ::BBTTest;
460         friend class ::FrameposPlusBeatsTest;
461         friend class ::TempoTest;
462
463         static Tempo    _default_tempo;
464         static Meter    _default_meter;
465
466         Metrics                       _metrics;
467         framecnt_t                    _frame_rate;
468         mutable Glib::Threads::RWLock lock;
469
470         void recompute_tempos (Metrics& metrics);
471         void recompute_meters (Metrics& metrics);
472         void recompute_map (Metrics& metrics, framepos_t end = -1);
473
474         framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
475
476         const MeterSection& first_meter() const;
477         MeterSection&       first_meter();
478         const TempoSection& first_tempo() const;
479         TempoSection&       first_tempo();
480
481         void do_insert (MetricSection* section);
482
483         void add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type);
484         void add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type);
485
486         void add_meter_locked (const Meter&, double beat, Timecode::BBT_Time where, bool recompute);
487         void add_meter_locked (const Meter&, framepos_t frame, bool recompute);
488
489         bool remove_tempo_locked (const TempoSection&);
490         bool remove_meter_locked (const MeterSection&);
491
492         TempoSection* copy_metrics_and_point (Metrics& copy, TempoSection* section);
493 };
494
495 }; /* namespace ARDOUR */
496
497 std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
498 std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
499 std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
500
501 #endif /* __ardour_tempo_h__ */