c64039bd064ce46b02b46dc09dc412a16abf67da
[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 class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
216 {
217   public:
218         TempoMap (framecnt_t frame_rate);
219         ~TempoMap();
220
221         /* measure-based stuff */
222
223         enum BBTPointType {
224                 Bar,
225                 Beat,
226         };
227
228         struct BBTPoint {
229                 framepos_t          frame;
230                 const MeterSection* meter;
231                 const TempoSection* tempo;
232                 uint32_t            bar;
233                 uint32_t            beat;
234
235                 BBTPoint (const MeterSection& m, const TempoSection& t, framepos_t f,
236                           uint32_t b, uint32_t e)
237                         : frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
238
239                 Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
240                 operator Timecode::BBT_Time() const { return bbt(); }
241                 operator framepos_t() const { return frame; }
242                 bool is_bar() const { return beat == 1; }
243         };
244
245         typedef std::vector<BBTPoint> BBTPointList;
246
247         template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
248                 Glib::Threads::RWLock::ReaderLock lm (lock);
249                 (obj.*method)(metrics);
250         }
251
252         void get_grid (BBTPointList::const_iterator&, BBTPointList::const_iterator&,
253                        framepos_t start, framepos_t end);
254
255         /* TEMPO- AND METER-SENSITIVE FUNCTIONS
256
257            bbt_time(), bbt_time_rt(), frame_time() and bbt_duration_at()
258            are all sensitive to tempo and meter, and will give answers
259            that align with the grid formed by tempo and meter sections.
260
261            They SHOULD NOT be used to determine the position of events
262            whose location is canonically defined in beats.
263         */
264
265         void bbt_time (framepos_t when, Timecode::BBT_Time&);
266
267         /* realtime safe variant of ::bbt_time(), will throw
268            std::logic_error if the map is not large enough
269            to provide an answer.
270         */
271         void       bbt_time_rt (framepos_t when, Timecode::BBT_Time&);
272         framepos_t frame_time (const Timecode::BBT_Time&);
273         framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
274
275         /* TEMPO-SENSITIVE FUNCTIONS
276
277            These next 4 functions will all take tempo in account and should be
278            used to determine position (and in the last case, distance in beats)
279            when tempo matters but meter does not.
280
281            They SHOULD be used to determine the position of events
282            whose location is canonically defined in beats.
283         */
284
285         framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const;
286         framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const;
287         framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const;
288         Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const;
289
290         static const Tempo& default_tempo() { return _default_tempo; }
291         static const Meter& default_meter() { return _default_meter; }
292
293         const Tempo& tempo_at (framepos_t) const;
294         const Meter& meter_at (framepos_t) const;
295
296         const TempoSection& tempo_section_at (framepos_t) const;
297         const MeterSection& meter_section_at (framepos_t) const;
298
299         void add_tempo (const Tempo&, Timecode::BBT_Time where);
300         void add_meter (const Meter&, Timecode::BBT_Time where);
301
302         void remove_tempo (const TempoSection&, bool send_signal);
303         void remove_meter (const MeterSection&, bool send_signal);
304
305         void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where);
306         void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
307
308         framepos_t round_to_bar  (framepos_t frame, RoundMode dir);
309         framepos_t round_to_beat (framepos_t frame, RoundMode dir);
310         framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
311
312         void set_length (framepos_t frames);
313
314         XMLNode& get_state (void);
315         int set_state (const XMLNode&, int version);
316
317         void dump (std::ostream&) const;
318         void clear ();
319
320         TempoMetric metric_at (Timecode::BBT_Time bbt) const;
321
322         /** Return the TempoMetric at frame @p t, and point @p last to the latest
323          * metric change <= t, if it is non-NULL.
324          */
325         TempoMetric metric_at (framepos_t, Metrics::const_iterator* last=NULL) const;
326
327         Metrics::const_iterator metrics_end() { return metrics.end(); }
328
329         void change_existing_tempo_at (framepos_t, double bpm, double note_type);
330         void change_initial_tempo (double bpm, double note_type);
331
332         void insert_time (framepos_t, framecnt_t);
333         bool remove_time (framepos_t where, framecnt_t amount);  //returns true if anything was moved
334
335         int n_tempos () const;
336         int n_meters () const;
337
338         framecnt_t frame_rate () const { return _frame_rate; }
339
340   private:
341
342         friend class ::BBTTest;
343         friend class ::FrameposPlusBeatsTest;
344         friend class ::TempoTest;
345
346         static Tempo    _default_tempo;
347         static Meter    _default_meter;
348
349         Metrics                       metrics;
350         framecnt_t                    _frame_rate;
351         mutable Glib::Threads::RWLock lock;
352         BBTPointList                  _map;
353
354         void recompute_map (bool reassign_tempo_bbt, framepos_t end = -1);
355         void extend_map (framepos_t end);
356         void require_map_to (framepos_t pos);
357         void require_map_to (const Timecode::BBT_Time&);
358         void _extend_map (TempoSection* tempo, MeterSection* meter,
359                           Metrics::iterator next_metric,
360                           Timecode::BBT_Time current, framepos_t current_frame, framepos_t end);
361
362         BBTPointList::const_iterator bbt_before_or_at (framepos_t);
363         BBTPointList::const_iterator bbt_before_or_at (const Timecode::BBT_Time&);
364         BBTPointList::const_iterator bbt_after_or_at (framepos_t);
365
366         framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
367         void bbt_time (framepos_t, Timecode::BBT_Time&, const BBTPointList::const_iterator&);
368         framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
369
370         const MeterSection& first_meter() const;
371         MeterSection&       first_meter();
372         const TempoSection& first_tempo() const;
373         TempoSection&       first_tempo();
374
375         void do_insert (MetricSection* section);
376
377         void add_tempo_locked (const Tempo&, Timecode::BBT_Time where, bool recompute);
378         void add_meter_locked (const Meter&, Timecode::BBT_Time where, bool recompute);
379
380         bool remove_tempo_locked (const TempoSection&);
381         bool remove_meter_locked (const MeterSection&);
382
383 };
384
385 }; /* namespace ARDOUR */
386
387 std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&);
388 std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&);
389 std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&);
390
391 #endif /* __ardour_tempo_h__ */