X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Ftempo.h;h=33d9fb937d6af3aa78396ca787cfe95f6ec75deb;hb=fef79d46bb54c0e9179e54a0977eeb602e4b2db3;hp=81fad2e0fcf46c69f5d4f9e08358ab630bb3e825;hpb=abac4ce854982c48b1cc825e573bdea5b13e8eb7;p=ardour.git diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 81fad2e0fc..33d9fb937d 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -105,10 +105,8 @@ class LIBARDOUR_API Meter { /** A section of timeline with a certain Tempo or Meter. */ class LIBARDOUR_API MetricSection { public: - MetricSection (double pulse) - : _pulse (pulse), _frame (0), _movable (true), _position_lock_style (MusicTime) {} - MetricSection (framepos_t frame) - : _pulse (0.0), _frame (frame), _movable (true), _position_lock_style (AudioTime) {} + MetricSection (double pulse, framepos_t frame, PositionLockStyle pls) + : _pulse (pulse), _frame (frame), _movable (true), _position_lock_style (pls) {} virtual ~MetricSection() {} @@ -142,19 +140,15 @@ private: /** A section of timeline with a certain Meter. */ class LIBARDOUR_API MeterSection : public MetricSection, public Meter { public: - MeterSection (double pulse, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type) - : MetricSection (pulse), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {} - MeterSection (framepos_t frame, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type) - : MetricSection (frame), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {} + MeterSection (double pulse, framepos_t frame, double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type, PositionLockStyle pls) + : MetricSection (pulse, frame, pls), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {} + MeterSection (const XMLNode&); static const std::string xml_state_node_name; XMLNode& get_state() const; - void set_pulse (double w) { - MetricSection::set_pulse (w); - } void set_beat (std::pair& w) { _beat = w.first; _bbt = w.second; @@ -177,10 +171,9 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo { Constant, }; - TempoSection (const double& pulse, double qpm, double note_type, Type tempo_type) - : MetricSection (pulse), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {} - TempoSection (framepos_t frame, double qpm, double note_type, Type tempo_type) - : MetricSection (frame), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {} + TempoSection (const double& pulse, const framepos_t& frame, double qpm, double note_type, Type tempo_type, PositionLockStyle pls) + : MetricSection (pulse, frame, pls), Tempo (qpm, note_type), _type (tempo_type), _c_func (0.0), _active (true), _locked_to_meter (false) {} + TempoSection (const XMLNode&); static const std::string xml_state_node_name; @@ -315,7 +308,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f, uint32_t b, uint32_t e, double func_c) - : frame (f), meter (m.note_divisor(), m.divisions_per_bar()), tempo (t.beats_per_minute(), t.note_type()), c (func_c), bar (b), beat (e) {} + : frame (f), meter (m.divisions_per_bar(), m.note_divisor()), tempo (t.beats_per_minute(), t.note_type()), c (func_c), bar (b), beat (e) {} Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); } operator Timecode::BBT_Time() const { return bbt(); } @@ -331,91 +324,45 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible void get_grid (std::vector&, framepos_t start, framepos_t end); - /* TEMPO- AND METER-SENSITIVE FUNCTIONS - - bbt_time(), beat_at_frame(), frame_at_beat(), tick_at_frame(), - frame_at_tick(),frame_time() and bbt_duration_at() - are all sensitive to tempo and meter, and will give answers - that align with the grid formed by tempo and meter sections. - - They SHOULD NOT be used to determine the position of events - whose location is canonically defined in beats. - */ - - void bbt_time (framepos_t when, Timecode::BBT_Time&); - - double beat_at_frame (const framecnt_t& frame) const; - framecnt_t frame_at_beat (const double& beat) const; - - framepos_t frame_time (const Timecode::BBT_Time&); - framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir); - - /* TEMPO-SENSITIVE FUNCTIONS - - These next 4 functions will all take tempo in account and should be - used to determine position (and in the last case, distance in beats) - when tempo matters but meter does not. - - They SHOULD be used to determine the position of events - whose location is canonically defined in beats. - */ - - framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const; - framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const; - framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const; - Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const; - static const Tempo& default_tempo() { return _default_tempo; } static const Meter& default_meter() { return _default_meter; } - const Tempo tempo_at (const framepos_t& frame) const; + /* because tempos may be ramped, this is only valid for the instant requested.*/ double frames_per_beat_at (const framepos_t&, const framecnt_t& sr) const; - const Meter& meter_at (framepos_t) const; - - const TempoSection& tempo_section_at (framepos_t frame) const; - const MeterSection& meter_section_at (framepos_t frame) const; + const TempoSection& tempo_section_at_frame (framepos_t frame) const; + const MeterSection& meter_section_at_frame (framepos_t frame) const; const MeterSection& meter_section_at_beat (double beat) const; - TempoSection* add_tempo (const Tempo&, const double& pulse, TempoSection::Type type); - TempoSection* add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type); + /** add a tempo section locked to pls. ignored values will be set in recompute_tempos() + * @param pulse pulse position of new section. ignored if pls == AudioTime + * @param frame frame position of new section. ignored if pls == MusicTime + * @param type type of new tempo section (Ramp, Constant) + */ + TempoSection* add_tempo (const Tempo&, const double& pulse, const framepos_t& frame, TempoSection::Type type, PositionLockStyle pls); - MeterSection* add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where); - MeterSection* add_meter (const Meter&, const framepos_t& frame, const double& beat, const Timecode::BBT_Time& where); + /** add an meter section locked to pls.. ignored values will be set in recompute_meters() + * @param beat beat position of new section + * @param where bbt position of new section + * @param frame frame position of new section. ignored if pls == MusicTime + */ + MeterSection* add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where, const framepos_t& frame, PositionLockStyle pls); void remove_tempo (const TempoSection&, bool send_signal); void remove_meter (const MeterSection&, bool send_signal); - framepos_t predict_tempo_frame (TempoSection* section, const Timecode::BBT_Time& bbt); - double predict_tempo_pulse (TempoSection* section, const framepos_t& frame); - - void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type); - void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& frame, TempoSection::Type type); + void replace_tempo (const TempoSection&, const Tempo&, const double& pulse, const framepos_t& frame + , TempoSection::Type type, PositionLockStyle pls); - void gui_move_tempo_frame (TempoSection*, const framepos_t& frame); - void gui_move_tempo_beat (TempoSection*, const double& beat); - void gui_move_tempo_pulse (TempoSection*, const double& pulse); - void gui_move_meter (MeterSection*, const framepos_t& frame); - void gui_move_meter (MeterSection*, const Timecode::BBT_Time& bbt); - bool gui_change_tempo (TempoSection*, const Tempo& bpm); - void gui_dilate_next_tempo (const framepos_t& frame, const framepos_t& end_frame); - void gui_dilate_tempo (MeterSection*, const framepos_t& frame); - void gui_dilate_tempo (TempoSection* tempo, const framepos_t& frame, const framepos_t& end_frame); - - bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt); - - void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where); - void replace_meter (const MeterSection&, const Meter&, const framepos_t& frame); + void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, const framepos_t& frame + , PositionLockStyle pls); framepos_t round_to_bar (framepos_t frame, RoundMode dir); framepos_t round_to_beat (framepos_t frame, RoundMode dir); framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir); - void round_bbt (Timecode::BBT_Time& when, const int32_t& snap_divisor, RoundMode dir); void set_length (framepos_t frames); - void fix_legacy_session(); - XMLNode& get_state (void); int set_state (const XMLNode&, int version); @@ -442,44 +389,109 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible framecnt_t frame_rate () const { return _frame_rate; } - double bbt_to_beats (const Timecode::BBT_Time& bbt); - Timecode::BBT_Time beats_to_bbt (const double& beats); - Timecode::BBT_Time pulse_to_bbt (const double& pulse); + /* TEMPO- AND METER-SENSITIVE FUNCTIONS + + bbt_at_frame(), frame_at_bbt(), beat_at_frame(), frame_at_beat(), tempo_at_beat() + and bbt_duration_at() + are all sensitive to tempo and meter, and will give answers + that align with the grid formed by tempo and meter sections. + They SHOULD NOT be used to determine the position of events + whose location is canonically defined in beats. + */ + + double beat_at_frame (const framecnt_t& frame) const; + framecnt_t frame_at_beat (const double& beat) const; + + Tempo tempo_at_frame (const framepos_t& frame) const; + framepos_t frame_at_tempo (const Tempo& tempo) const; + + Tempo tempo_at_beat (const double& beat) const; + + const Meter& meter_at_frame (framepos_t) const; + + /* you probably only need to use pulses when moving tempos */ double pulse_at_beat (const double& beat) const; double beat_at_pulse (const double& pulse) const; double pulse_at_frame (const framecnt_t& frame) const; framecnt_t frame_at_pulse (const double& pulse) const; + /* bbt - it's nearly always better to use beats.*/ + Timecode::BBT_Time bbt_at_frame (framepos_t when); + Timecode::BBT_Time bbt_at_frame_rt (framepos_t when); + framepos_t frame_at_bbt (const Timecode::BBT_Time&); + + double beat_at_bbt (const Timecode::BBT_Time& bbt); + Timecode::BBT_Time bbt_at_beat (const double& beats); + + double pulse_at_bbt (const Timecode::BBT_Time& bbt); + Timecode::BBT_Time bbt_at_pulse (const double& pulse); + + framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir); + + /* TEMPO-SENSITIVE FUNCTIONS + + These next 4 functions will all take tempo in account and should be + used to determine position (and in the last case, distance in beats) + when tempo matters but meter does not. + + They SHOULD be used to determine the position of events + whose location is canonically defined in beats. + */ + + framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const; + framepos_t framepos_plus_beats (framepos_t, Evoral::Beats) const; + framepos_t framepos_minus_beats (framepos_t, Evoral::Beats) const; + Evoral::Beats framewalk_to_beats (framepos_t pos, framecnt_t distance) const; + + void gui_move_tempo (TempoSection*, const framepos_t& frame, const int& sub_num); + void gui_move_meter (MeterSection*, const framepos_t& frame); + bool gui_change_tempo (TempoSection*, const Tempo& bpm); + void gui_dilate_tempo (TempoSection* tempo, const framepos_t& frame, const framepos_t& end_frame, const double& pulse); + + std::pair predict_tempo_position (TempoSection* section, const Timecode::BBT_Time& bbt); + bool can_solve_bbt (TempoSection* section, const Timecode::BBT_Time& bbt); + PBD::Signal0 MetricPositionChanged; + void fix_legacy_session(); private: + + double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const; + framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const; + double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const; double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const; + double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const; framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& pulse) const; - double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const; - framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const; - double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ; - Timecode::BBT_Time beats_to_bbt_locked (const Metrics& metrics, const double& beats) const; + Tempo tempo_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const; + framepos_t frame_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const; - framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&) const; + Timecode::BBT_Time bbt_at_frame_locked (const Metrics& metrics, const framepos_t& frame) const; + framepos_t frame_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&) const; - const MeterSection& meter_section_at_locked (const Metrics& metrics, framepos_t frame) const; - const TempoSection& tempo_section_at_locked (const Metrics& metrics, framepos_t frame) const; - const MeterSection& meter_section_at_beat_locked (const Metrics& metrics, const double& beat) const; + double beat_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ; + Timecode::BBT_Time bbt_at_beat_locked (const Metrics& metrics, const double& beats) const; + + double pulse_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const; + Timecode::BBT_Time bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const; + + const TempoSection& tempo_section_at_frame_locked (const Metrics& metrics, framepos_t frame) const; const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const; - const TempoSection& tempo_section_at_pulse_locked (const Metrics& metrics, const double& pulse) const; - const Tempo tempo_at_locked (const Metrics& metrics, const framepos_t& frame) const; - bool check_solved (const Metrics& metrics, bool by_frame) const; + const MeterSection& meter_section_at_frame_locked (const Metrics& metrics, framepos_t frame) const; + const MeterSection& meter_section_at_beat_locked (const Metrics& metrics, const double& beat) const; + + bool check_solved (const Metrics& metrics) const; bool set_active_tempos (const Metrics& metrics, const framepos_t& frame); - bool solve_map (Metrics& metrics, TempoSection* section, const framepos_t& frame); - bool solve_map (Metrics& metrics, TempoSection* section, const double& pulse); - bool solve_map (Metrics& metrics, MeterSection* section, const framepos_t& frame); - bool solve_map (Metrics& metrics, MeterSection* section, const Timecode::BBT_Time& bbt); + + bool solve_map_frame (Metrics& metrics, TempoSection* section, const framepos_t& frame); + bool solve_map_pulse (Metrics& metrics, TempoSection* section, const double& pulse); + bool solve_map_frame (Metrics& metrics, MeterSection* section, const framepos_t& frame); + bool solve_map_bbt (Metrics& metrics, MeterSection* section, const Timecode::BBT_Time& bbt); friend class ::BBTTest; friend class ::FrameposPlusBeatsTest; @@ -505,11 +517,11 @@ private: void do_insert (MetricSection* section); - TempoSection* add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type); - TempoSection* add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type); + TempoSection* add_tempo_locked (const Tempo&, double pulse, framepos_t frame + , TempoSection::Type type, PositionLockStyle pls, bool recompute, bool locked_to_meter = false); - MeterSection* add_meter_locked (const Meter&, double beat, const Timecode::BBT_Time& where, bool recompute); - MeterSection* add_meter_locked (const Meter&, framepos_t frame, double beat, const Timecode::BBT_Time& where, bool recompute); + MeterSection* add_meter_locked (const Meter&, double beat, const Timecode::BBT_Time& where, framepos_t frame + , PositionLockStyle pls, bool recompute); bool remove_tempo_locked (const TempoSection&); bool remove_meter_locked (const MeterSection&);