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