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