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