Tempo ramps - complete 'music locked meters are now positioned using beats' transition.
[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 pulse, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type)
142                 : MetricSection (pulse), Meter (bpb, note_type), _bbt (bbt),  _beat (beat) {}
143         MeterSection (framepos_t frame, double beat, double bpb, double note_type)
144                 : MetricSection (frame), Meter (bpb, note_type), _bbt (1, 1, 0), _beat (beat) {}
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 (double w) {
152                 MetricSection::set_pulse (w);
153         }
154         void set_beat (std::pair<double, Timecode::BBT_Time>& w) {
155                 _beat = w.first;
156                 _bbt = w.second;
157         }
158
159         const Timecode::BBT_Time& bbt() const { return _bbt; }
160         const double& beat () const { return _beat; }
161         void set_beat (double beat) { _beat = beat; }
162
163 private:
164         Timecode::BBT_Time _bbt;
165         double _beat;
166 };
167
168 /** A section of timeline with a certain Tempo. */
169 class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
170   public:
171         enum Type {
172                 Ramp,
173                 Constant,
174         };
175
176         TempoSection (const double& beat, double qpm, double note_type, Type tempo_type)
177                 : MetricSection (beat), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type), _c_func (0.0)  {}
178         TempoSection (framepos_t frame, double qpm, double note_type, Type tempo_type)
179                 : MetricSection (frame), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type), _c_func (0.0) {}
180         TempoSection (const XMLNode&);
181
182         static const std::string xml_state_node_name;
183
184         XMLNode& get_state() const;
185
186         void update_bar_offset_from_bbt (const Meter&);
187         void update_bbt_time_from_bar_offset (const Meter&);
188         double bar_offset() const { return _bar_offset; }
189
190         void set_type (Type type);
191         Type type () const { return _type; }
192
193         double tempo_at_frame (const framepos_t& frame, const framecnt_t& frame_rate) const;
194         framepos_t frame_at_tempo (const double& ppm, const double& beat, const framecnt_t& frame_rate) const;
195
196         double tempo_at_pulse (const double& pulse) const;
197         double pulse_at_tempo (const double& ppm, const framepos_t& frame, const framecnt_t& frame_rate) const;
198
199         double pulse_at_frame (const framepos_t& frame, const framecnt_t& frame_rate) const;
200         framepos_t frame_at_pulse (const double& pulse, const framecnt_t& frame_rate) const;
201
202         double compute_c_func_pulse (const double& end_bpm, const double& end_pulse, const framecnt_t& frame_rate);
203         double compute_c_func_frame (const double& end_bpm, const framepos_t& end_frame, const framecnt_t& frame_rate) const;
204
205         double get_c_func () const { return _c_func; }
206         void set_c_func (double c_func) { _c_func = c_func; }
207
208         Timecode::BBT_Time legacy_bbt () { return _legacy_bbt; }
209
210   private:
211
212         framecnt_t minute_to_frame (const double& time, const framecnt_t& frame_rate) const;
213         double frame_to_minute (const framecnt_t& frame, const framecnt_t& frame_rate) const;
214
215         /*  tempo ramp functions. zero-based with time in minutes,
216          * 'tick tempo' in ticks per minute and tempo in bpm.
217          *  time relative to section start.
218          */
219         double a_func (double end_tpm, double c_func) const;
220         double c_func (double end_tpm, double end_time) const;
221
222         double pulse_tempo_at_time (const double& time) const;
223         double time_at_pulse_tempo (const double& pulse_tempo) const;
224
225         double pulse_tempo_at_pulse (const double& pulse) const;
226         double pulse_at_pulse_tempo (const double& pulse_tempo) const;
227
228         double pulse_at_time (const double& time) const;
229         double time_at_pulse (const double& pulse) const;
230
231         /* this value provides a fractional offset into the bar in which
232            the tempo section is located in. A value of 0.0 indicates that
233            it occurs on the first beat of the bar, a value of 0.5 indicates
234            that it occurs halfway through the bar and so on.
235
236            this enables us to keep the tempo change at the same relative
237            position within the bar if/when the meter changes.
238         */
239         double _bar_offset;
240         Type _type;
241         double _c_func;
242         Timecode::BBT_Time _legacy_bbt;
243 };
244
245 typedef std::list<MetricSection*> Metrics;
246
247 /** Helper class to keep track of the Meter *AND* Tempo in effect
248     at a given point in time.
249 */
250 class LIBARDOUR_API TempoMetric {
251   public:
252         TempoMetric (const Meter& m, const Tempo& t)
253                 : _meter (&m), _tempo (&t), _frame (0) {}
254
255         void set_tempo (const Tempo& t)              { _tempo = &t; }
256         void set_meter (const Meter& m)              { _meter = &m; }
257         void set_frame (framepos_t f)                { _frame = f; }
258         void set_pulse (const double& p)             { _pulse = p; }
259
260         void set_metric (const MetricSection* section) {
261                 const MeterSection* meter;
262                 const TempoSection* tempo;
263                 if ((meter = dynamic_cast<const MeterSection*>(section))) {
264                         set_meter(*meter);
265                 } else if ((tempo = dynamic_cast<const TempoSection*>(section))) {
266                         set_tempo(*tempo);
267                 }
268
269                 set_frame (section->frame());
270                 set_pulse (section->pulse());
271         }
272
273         const Meter&              meter() const { return *_meter; }
274         const Tempo&              tempo() const { return *_tempo; }
275         framepos_t                frame() const { return _frame; }
276         const double&             pulse() const { return _pulse; }
277
278   private:
279         const Meter*       _meter;
280         const Tempo*       _tempo;
281         framepos_t         _frame;
282         double             _pulse;
283 };
284
285 /** Tempo Map - mapping of timecode to musical time.
286  * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo
287  */
288 class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
289 {
290   public:
291         TempoMap (framecnt_t frame_rate);
292         ~TempoMap();
293
294         /* measure-based stuff */
295
296         enum BBTPointType {
297                 Bar,
298                 Beat,
299         };
300
301         struct BBTPoint {
302                 framepos_t          frame;
303                 const MeterSection* meter;
304                 const Tempo tempo;
305                 uint32_t            bar;
306                 uint32_t            beat;
307
308                 BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f,
309                           uint32_t b, uint32_t e)
310                 : frame (f), meter (&m), tempo (t.beats_per_minute(), t.note_type()), bar (b), beat (e) {}
311
312                 Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
313                 operator Timecode::BBT_Time() const { return bbt(); }
314                 operator framepos_t() const { return frame; }
315                 bool is_bar() const { return beat == 1; }
316         };
317
318         template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
319                 Glib::Threads::RWLock::ReaderLock lm (lock);
320                 (obj.*method)(_metrics);
321         }
322
323         void get_grid (std::vector<BBTPoint>&,
324                        framepos_t start, framepos_t end);
325
326         /* TEMPO- AND METER-SENSITIVE FUNCTIONS
327
328            bbt_time(), beat_at_frame(), frame_at_beat(), tick_at_frame(),
329            frame_at_tick(),frame_time() and bbt_duration_at()
330            are all sensitive to tempo and meter, and will give answers
331            that align with the grid formed by tempo and meter sections.
332
333            They SHOULD NOT be used to determine the position of events
334            whose location is canonically defined in beats.
335         */
336
337         void bbt_time (framepos_t when, Timecode::BBT_Time&);
338
339         double beat_at_frame (const framecnt_t& frame) const;
340         framecnt_t frame_at_beat (const double& beat) const;
341
342         framepos_t frame_time (const Timecode::BBT_Time&);
343         framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
344
345         /* TEMPO-SENSITIVE FUNCTIONS
346
347            These next 4 functions will all take tempo in account and should be
348            used to determine position (and in the last case, distance in beats)
349            when tempo matters but meter does not.
350
351            They SHOULD be used to determine the position of events
352            whose location is canonically defined in beats.
353         */
354
355         framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
356         framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const;
357         framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const;
358         Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const;
359
360         static const Tempo& default_tempo() { return _default_tempo; }
361         static const Meter& default_meter() { return _default_meter; }
362
363         const Tempo tempo_at (const framepos_t& frame) const;
364         double frames_per_beat_at (const framepos_t&, const framecnt_t& sr) const;
365
366         const Meter& meter_at (framepos_t) const;
367
368         const TempoSection& tempo_section_at (framepos_t frame) const;
369         const MeterSection& meter_section_at (framepos_t frame) const;
370
371         void add_tempo (const Tempo&, const double& pulse, TempoSection::Type type);
372         void add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type);
373
374         void add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where);
375         void add_meter (const Meter&, const framepos_t& frame);
376
377         void remove_tempo (const TempoSection&, bool send_signal);
378         void remove_meter (const MeterSection&, bool send_signal);
379
380         framepos_t predict_tempo_frame (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt);
381         double predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame);
382
383         void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
384         void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& frame, TempoSection::Type type);
385
386         void gui_move_tempo_frame (TempoSection*, const Tempo& bpm, const framepos_t& frame);
387         void gui_move_tempo_beat (TempoSection*, const Tempo& bpm, const double& frame);
388         void gui_move_meter (MeterSection*, const Meter& mt, const framepos_t& frame);
389         void gui_move_meter (MeterSection*, const Meter& mt, const double& beat);
390
391         bool can_solve_bbt (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt);
392
393         void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
394         void replace_meter (const MeterSection&, const Meter&, const framepos_t& frame);
395
396         framepos_t round_to_bar  (framepos_t frame, RoundMode dir);
397         framepos_t round_to_beat (framepos_t frame, RoundMode dir);
398         framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
399
400         void set_length (framepos_t frames);
401
402         XMLNode& get_state (void);
403         int set_state (const XMLNode&, int version);
404
405         void dump (const Metrics& metrics, std::ostream&) const;
406         void clear ();
407
408         TempoMetric metric_at (Timecode::BBT_Time bbt) const;
409
410         /** Return the TempoMetric at frame @p t, and point @p last to the latest
411          * metric change <= t, if it is non-NULL.
412          */
413         TempoMetric metric_at (framepos_t, Metrics::const_iterator* last=NULL) const;
414
415         Metrics::const_iterator metrics_end() { return _metrics.end(); }
416
417         void change_existing_tempo_at (framepos_t, double bpm, double note_type);
418         void change_initial_tempo (double bpm, double note_type);
419
420         void insert_time (framepos_t, framecnt_t);
421         bool remove_time (framepos_t where, framecnt_t amount);  //returns true if anything was moved
422
423         int n_tempos () const;
424         int n_meters () const;
425
426         framecnt_t frame_rate () const { return _frame_rate; }
427
428         double bbt_to_beats (const Timecode::BBT_Time& bbt);
429         Timecode::BBT_Time beats_to_bbt (const double& beats);
430         Timecode::BBT_Time pulse_to_bbt (const double& pulse);
431
432         double pulse_at_beat (const double& beat) const;
433         double beat_at_pulse (const double& pulse) const;
434
435         PBD::Signal0<void> MetricPositionChanged;
436
437 private:
438         double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
439         double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
440         double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
441         framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& beat) const;
442
443         double pulse_offset_at (const Metrics& metrics, const double& pulse) const;
444         frameoffset_t frame_offset_at (const Metrics& metrics, const framepos_t& frame) const;
445
446         double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
447         framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
448         double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
449         Timecode::BBT_Time beats_to_bbt_locked (const Metrics& metrics, const double& beats) const;
450
451         framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
452
453         const MeterSection& meter_section_at_locked (framepos_t frame) const;
454         const TempoSection& tempo_section_at_locked (framepos_t frame) const;
455
456         bool check_solved (Metrics& metrics, bool by_frame);
457         bool solve_map (Metrics& metrics, TempoSection* section, const Tempo& bpm, const framepos_t& frame);
458         bool solve_map (Metrics& metrics, TempoSection* section, const Tempo& bpm, const double& pulse);
459         void solve_map (Metrics& metrics, MeterSection* section, const Meter& mt, const framepos_t& frame);
460         void solve_map (Metrics& metrics, MeterSection* section, const Meter& mt, const double& pulse);
461
462         friend class ::BBTTest;
463         friend class ::FrameposPlusBeatsTest;
464         friend class ::TempoTest;
465
466         static Tempo    _default_tempo;
467         static Meter    _default_meter;
468
469         Metrics                       _metrics;
470         framecnt_t                    _frame_rate;
471         mutable Glib::Threads::RWLock lock;
472
473         void recompute_tempos (Metrics& metrics);
474         void recompute_meters (Metrics& metrics);
475         void recompute_map (Metrics& metrics, framepos_t end = -1);
476
477         framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
478
479         const MeterSection& first_meter() const;
480         MeterSection&       first_meter();
481         const TempoSection& first_tempo() const;
482         TempoSection&       first_tempo();
483
484         void do_insert (MetricSection* section);
485
486         void add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type);
487         void add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type);
488
489         void add_meter_locked (const Meter&, double beat, Timecode::BBT_Time where, bool recompute);
490         void add_meter_locked (const Meter&, framepos_t frame, bool recompute);
491
492         bool remove_tempo_locked (const TempoSection&);
493         bool remove_meter_locked (const MeterSection&);
494
495         TempoSection* copy_metrics_and_point (Metrics& copy, TempoSection* section);
496 };
497
498 }; /* namespace ARDOUR */
499
500 std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
501 std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
502 std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
503
504 #endif /* __ardour_tempo_h__ */