diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc index e5462008b4..8daa927d5a 100644 --- a/gtk2_ardour/automation_controller.cc +++ b/gtk2_ardour/automation_controller.cc @@ -284,7 +284,7 @@ AutomationController::set_freq_beats(double beats) const ARDOUR::ParameterDescriptor& desc = _controllable->desc(); const ARDOUR::Session& session = _controllable->session(); const samplepos_t pos = session.transport_sample(); - const ARDOUR::Tempo& tempo = session.tempo_map().tempo_at_sample (pos); + const Temporal::Tempo& tempo = session.tempo_map().metric_at (pos).tempo(); const double bpm = tempo.note_types_per_minute(); const double bps = bpm / 60.0; const double freq = bps / beats; diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 64fc8682d2..136bb70d23 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -77,7 +77,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; using namespace Editing; - +using namespace Temporal; #define TIME_TO_SAMPLES(x) (_distance_measure (x, Temporal::AudioTime)) #define SAMPLES_TO_TIME(x) (_distance_measure (x, alist->time_domain())) @@ -496,9 +496,8 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) before_x = line.nth (front()->view_index() - 1)->get_x(); const samplepos_t pos = e.pixel_to_sample(before_x); - const Meter& meter = map.meter_at_sample (pos); - const samplecnt_t len = ceil (meter.samples_per_bar (map.tempo_at_sample (pos), e.session()->sample_rate()) - / (Temporal::ticks_per_beat * meter.divisions_per_bar()) ); + const TempoMetric& metric = map.metric_at (pos); + const samplecnt_t len = ceil (metric.samples_per_bar (pos) / (Temporal::ticks_per_beat * metric.meter().divisions_per_bar())); const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len); before_x += one_tick_in_pixels; @@ -512,9 +511,8 @@ AutomationLine::ContiguousControlPoints::compute_x_bounds (PublicEditor& e) after_x = line.nth (back()->view_index() + 1)->get_x(); const samplepos_t pos = e.pixel_to_sample(after_x); - const Meter& meter = map.meter_at_sample (pos); - const samplecnt_t len = ceil (meter.samples_per_bar (map.tempo_at_sample (pos), e.session()->sample_rate()) - / (Temporal::ticks_per_beat * meter.divisions_per_bar())); + const TempoMetric& metric = map.metric_at (pos); + const samplecnt_t len = ceil (metric.samples_per_bar (pos) / (Temporal::ticks_per_beat * metric.meter().divisions_per_bar())); const double one_tick_in_pixels = e.sample_to_pixel_unrounded (len); after_x -= one_tick_in_pixels; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index bfffe4a25b..93352bf86b 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1805,9 +1805,9 @@ private: Curves tempo_curves; void remove_metric_marks (); - void draw_metric_marks (const ARDOUR::Metrics& metrics); + void draw_metric_marks (const Temporal::TempoMap::Metrics& metrics); - void compute_current_bbt_points (std::vector& grid, samplepos_t left, samplepos_t right); + void compute_current_bbt_points (std::vector& grid, samplepos_t left, samplepos_t right); void tempo_map_changed (const PBD::PropertyChange&); void tempometric_position_changed (const PBD::PropertyChange&); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index abbc044681..5ba7e96203 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -74,6 +74,8 @@ using namespace PBD; using namespace Gtk; using namespace Gtkmm2ext; using namespace Editing; +using namespace Temporal; + using std::string; /* Functions supporting the incorporation of external (non-captured) audio material into ardour */ @@ -280,7 +282,9 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, timepos_t const & pos) } const samplecnt_t sample_rate = _session->sample_rate (); - TempoMap new_map (sample_rate); +#warning NUTEMPO need to be able to create a tempo map with no entries + // TempoMap new_map (sample_rate); + TempoMap new_map (Tempo (120), Meter (4, 4), sample_rate); Meter last_meter (4.0, 4.0); bool have_initial_meter = false; @@ -294,10 +298,12 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, timepos_t const & pos) Temporal::BBT_Time bbt; /* 1|1|0 which is correct for the no-meter case */ if (have_initial_meter) { - new_map.add_tempo (tempo, t->time_pulses/ (double)smf.ppqn() / 4.0, 0, MusicTime); +#warning NUTEMPO check API for this + // new_map.add_tempo (tempo, t->time_pulses/ (double)smf.ppqn() / 4.0, 0, BeatTime); if (!(meter == last_meter)) { - bbt = new_map.bbt_at_quarter_note (t->time_pulses/(double)smf.ppqn()); - new_map.add_meter (meter, bbt, 0, MusicTime); + bbt = new_map.bbt_at (Beats::from_double (t->time_pulses/(double)smf.ppqn())); +#warning NUTEMPO check API for this + //new_map.add_meter (meter, bbt, 0, MusicTime); } } else { @@ -311,7 +317,8 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, timepos_t const & pos) last_meter = meter; } - _session->tempo_map() = new_map; +#warning NUTEMPO need an assignment API for TempoMap + //_session->tempo_map() = new_map; } void diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 1973d14c8e..f6e5e2258b 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3717,7 +3717,7 @@ BBTRulerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) #warning NUTEMPO fixme needs new tempo map #if 0 TempoMap& map (_editor->session()->tempo_map()); - _tempo = const_cast (&map.tempo_section_at_sample (raw_grab_sample())); + _tempo = const_cast (&map.metric_at (raw_grab_sample().tempo())); if (adjusted_current_time (event, false) <= _tempo->time()) { _drag_valid = false; @@ -3748,7 +3748,7 @@ BBTRulerDrag::setup_pointer_offset () /* get current state */ _before_state = &map.get_state(); - const double beat_at_sample = max (0.0, map.beat_at_sample (raw_grab_sample())); + const double beat_at_sample = max (0.0, map.beat_at (raw_grab_sample())); const uint32_t divisions = _editor->get_grid_beat_divisions (0); double beat = 0.0; @@ -3762,7 +3762,7 @@ BBTRulerDrag::setup_pointer_offset () beat = floor (beat_at_sample) + (floor (((beat_at_sample - floor (beat_at_sample)) * 4)) / 4); } - _grab_qn = map.quarter_note_at_beat (beat); + _grab_qn = map.quarter_note_at (beat); _pointer_offset = raw_grab_sample() - map.sample_at_quarter_note (_grab_qn); diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 6c2f687ae9..15e74fdb02 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -875,7 +875,7 @@ private: bool _copy; bool _movable; - ARDOUR::Tempo _grab_bpm; + Temporal::Tempo _grab_bpm; double _grab_qn; XMLNode* _before_state; }; @@ -931,9 +931,9 @@ public: private: double _grab_qn; - ARDOUR::Tempo _grab_tempo; - ARDOUR::TempoSection* _tempo; - ARDOUR::TempoSection* _next_tempo; + Temporal::Tempo _grab_tempo; + Temporal::TempoPoint* _tempo; + Temporal::TempoPoint* _next_tempo; bool _drag_valid; XMLNode* _before_state; }; @@ -962,7 +962,7 @@ public: private: double _grab_qn; - ARDOUR::TempoSection* _tempo; + Temporal::TempoPoint* _tempo; XMLNode* _before_state; bool _drag_valid; }; diff --git a/gtk2_ardour/export_format_dialog.cc b/gtk2_ardour/export_format_dialog.cc index 8b7ab6b540..af03123dad 100644 --- a/gtk2_ardour/export_format_dialog.cc +++ b/gtk2_ardour/export_format_dialog.cc @@ -1032,7 +1032,7 @@ ExportFormatDialog::update_time (AnyTime& time, AudioClock const& clock) break; case AudioClock::BBT: time.type = AnyTime::BBT; - _session->bbt_time (samples, time.bbt); + _session->bbt_time (timepos_t (samples), time.bbt); break; case AudioClock::Seconds: case AudioClock::MinSec: diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc index 2370709c6d..480aa0afa5 100644 --- a/gtk2_ardour/tempo_dialog.cc +++ b/gtk2_ardour/tempo_dialog.cc @@ -40,6 +40,7 @@ using namespace Gtk; using namespace Gtkmm2ext; using namespace ARDOUR; using namespace PBD; +using namespace Temporal; TempoDialog::TempoDialog (TempoMap& map, samplepos_t sample, const string&) : ArdourDialog (_("New Tempo")) @@ -55,16 +56,17 @@ TempoDialog::TempoDialog (TempoMap& map, samplepos_t sample, const string&) , pulse_selector_label (_("Pulse:"), ALIGN_LEFT, ALIGN_CENTER) , tap_tempo_button (_("Tap tempo")) { - Tempo tempo (map.tempo_at_sample (sample)); - Temporal::BBT_Time when (map.bbt_at_sample (sample)); + TempoMetric metric (map.metric_at (sample)); + Temporal::BBT_Time when (metric.bbt_at (sample)); + Tempo& tempo (metric.tempo()); - init (when, tempo.note_types_per_minute(), tempo.end_note_types_per_minute(), tempo.note_type(), TempoSection::Constant, true, MusicTime); + init (when, tempo.note_types_per_minute(), tempo.end_note_types_per_minute(), tempo.note_type(), Tempo::Constant, true, BeatTime); } -TempoDialog::TempoDialog (TempoMap& map, TempoSection& section, const string&) +TempoDialog::TempoDialog (TempoMap& map, TempoPoint& point, const string&) : ArdourDialog (_("Edit Tempo")) , _map (&map) - , _section (§ion) + , _section (&point) , bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0) , bpm_spinner (bpm_adjustment) , end_bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0) @@ -75,13 +77,13 @@ TempoDialog::TempoDialog (TempoMap& map, TempoSection& section, const string&) , pulse_selector_label (_("Pulse:"), ALIGN_LEFT, ALIGN_CENTER) , tap_tempo_button (_("Tap tempo")) { - Temporal::BBT_Time when (map.bbt_at_sample (section.sample())); - init (when, section.note_types_per_minute(), section.end_note_types_per_minute(), section.note_type(), section.type() - , section.initial() || section.locked_to_meter(), section.position_lock_style()); + Temporal::BBT_Time when (map.bbt_at (point.time())); + init (when, _section->note_types_per_minute(), _section->end_note_types_per_minute(), _section->note_type(), _section->type(), + (map.is_initial (point) ||(map.time_domain() == Temporal::BarTime)), map.time_domain()); } void -TempoDialog::init (const Temporal::BBT_Time& when, double bpm, double end_bpm, double note_type, TempoSection::Type type, bool initial, PositionLockStyle style) +TempoDialog::init (const Temporal::BBT_Time& when, double bpm, double end_bpm, double note_type, Tempo::Type type, bool initial, TimeDomain style) { vector strings; NoteTypes::iterator x; diff --git a/gtk2_ardour/tempo_dialog.h b/gtk2_ardour/tempo_dialog.h index 252b2056e6..5c39f13ddb 100644 --- a/gtk2_ardour/tempo_dialog.h +++ b/gtk2_ardour/tempo_dialog.h @@ -43,18 +43,18 @@ class TempoDialog : public ArdourDialog { public: - TempoDialog (ARDOUR::TempoMap&, samplepos_t, const std::string & action); - TempoDialog (ARDOUR::TempoMap&, ARDOUR::TempoSection&, const std::string & action); + TempoDialog (Temporal::TempoMap&, samplepos_t, const std::string & action); + TempoDialog (Temporal::TempoMap&, Temporal::TempoPoint&, const std::string & action); double get_bpm (); double get_end_bpm (); double get_note_type (); bool get_bbt_time (Temporal::BBT_Time&); - ARDOUR::TempoSection::Type get_tempo_type (); - ARDOUR::PositionLockStyle get_lock_style (); + Temporal::Tempo::Type get_tempo_type (); + Temporal::TimeDomain get_lock_style (); private: - void init (const Temporal::BBT_Time& start, double bpm, double end_bpm, double note_type, ARDOUR::TempoSection::Type type, bool movable, ARDOUR::PositionLockStyle style); + void init (const Temporal::BBT_Time& start, double bpm, double end_bpm, double note_type, Temporal::TempoPoint::Type type, bool movable, Temporal::TimeDomain style); bool is_user_input_valid() const; void bpm_changed (); bool bpm_button_press (GdkEventButton* ); @@ -72,10 +72,10 @@ private: typedef std::map NoteTypes; NoteTypes note_types; - typedef std::map TempoTypes; + typedef std::map TempoTypes; TempoTypes tempo_types; - typedef std::map LockStyles; + typedef std::map LockStyles; LockStyles lock_styles; bool tapped; // whether the tap-tempo button has been clicked @@ -84,8 +84,8 @@ private: double last_t; gint64 first_t; - ARDOUR::TempoMap* _map; - ARDOUR::TempoSection* _section; + Temporal::TempoMap* _map; + Temporal::TempoPoint* _section; Gtk::ComboBoxText pulse_selector; Gtk::Adjustment bpm_adjustment; @@ -107,16 +107,16 @@ class MeterDialog : public ArdourDialog { public: - MeterDialog (ARDOUR::TempoMap&, samplepos_t, const std::string & action); - MeterDialog (ARDOUR::TempoMap&, ARDOUR::MeterSection&, const std::string & action); + MeterDialog (Temporal::TempoMap&, samplepos_t, const std::string & action); + MeterDialog (Temporal::TempoMap&, Temporal::MeterPoint&, const std::string & action); double get_bpb (); double get_note_type (); - ARDOUR::PositionLockStyle get_lock_style (); + Temporal::TimeDomain get_lock_style (); bool get_bbt_time (Temporal::BBT_Time&); private: - void init (const Temporal::BBT_Time&, double, double, bool, ARDOUR::PositionLockStyle style); + void init (const Temporal::BBT_Time&, double, double, bool, Temporal::TimeDomain style); bool is_user_input_valid() const; bool entry_key_press (GdkEventKey* ); bool entry_key_release (GdkEventKey* ); @@ -126,7 +126,7 @@ private: typedef std::map NoteTypes; NoteTypes note_types; - typedef std::map LockStyles; + typedef std::map LockStyles; LockStyles lock_styles; Gtk::Entry bpb_entry; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 6be0875db4..c747860642 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -116,6 +116,10 @@ namespace Evoral { class Curve; } +namespace Temporal { +class TempoMap; +} + namespace ARDOUR { class Amp; @@ -168,7 +172,6 @@ class SessionPlaylists; class SoloMuteRelease; class Source; class Speakers; -class TempoMap; class TransportMaster; struct TransportFSM; class Track; @@ -782,7 +785,7 @@ public: void sync_time_vars(); - void bbt_time (samplepos_t when, Temporal::BBT_Time&); + void bbt_time (Temporal::timepos_t const & when, Temporal::BBT_Time&); void timecode_to_sample(Timecode::Time& timecode, samplepos_t& sample, bool use_offset, bool use_subframes) const; void sample_to_timecode(samplepos_t sample, Timecode::Time& timecode, bool use_offset, bool use_subframes) const; void timecode_time (Timecode::Time &); @@ -825,8 +828,8 @@ public: bool loop_is_possible () const; PBD::Signal0 PunchLoopConstraintChange; - TempoMap& tempo_map() { return *_tempo_map; } - const TempoMap& tempo_map() const { return *_tempo_map; } + Temporal::TempoMap& tempo_map() { return *_tempo_map; } + const Temporal::TempoMap& tempo_map() const { return *_tempo_map; } void maybe_update_tempo_from_midiclock_tempo (float bpm); unsigned int get_xrun_count () const {return _xrun_count; } @@ -1864,8 +1867,8 @@ private: int send_full_time_code (samplepos_t, pframes_t nframes); void send_song_position_pointer (samplepos_t); - TempoMap *_tempo_map; - void tempo_map_changed (const PBD::PropertyChange&); + Temporal::TempoMap *_tempo_map; + void tempo_map_changed (); /* edit/mix groups */ diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index f6a857e7cd..297047c691 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -1,645 +1,6 @@ -/* - * Copyright (C) 2006-2017 Paul Davis - * Copyright (C) 2006 Hans Fugal - * Copyright (C) 2007-2015 David Robillard - * Copyright (C) 2009-2012 Carl Hetherington - * Copyright (C) 2015-2017 Ben Loftis - * Copyright (C) 2015-2017 Nick Mainsbridge - * Copyright (C) 2015-2019 Robin Gareus - * Copyright (C) 2015 Colin Fletcher - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - #ifndef __ardour_tempo_h__ #define __ardour_tempo_h__ -#include -#include -#include -#include -#include - -#include "pbd/undo.h" -#include "pbd/enum_convert.h" - -#include "pbd/stateful.h" -#include "pbd/statefuldestructible.h" - -#include "temporal/beats.h" - -#include "ardour/ardour.h" - -class BBTTest; -class FrameposPlusBeatsTest; -class FrameposMinusBeatsTest; -class TempoTest; -class XMLNode; - -namespace ARDOUR { - -enum PositionLockStyle { - AudioTime, - MusicTime -}; - -class Meter; -class TempoMap; - -// Find a better place for these -LIBARDOUR_API bool bbt_time_to_string (const Temporal::BBT_Time& bbt, std::string& str); -LIBARDOUR_API bool string_to_bbt_time (const std::string& str, Temporal::BBT_Time& bbt); - -/** Tempo, the speed at which musical time progresses (BPM). */ -class LIBARDOUR_API Tempo { - public: - /** - * @param npm Note Types per minute - * @param type Note Type (default `4': quarter note) - */ - Tempo (double npm, double type=4.0) // defaulting to quarter note - : _note_types_per_minute (npm), _note_type (type), _end_note_types_per_minute (npm) {} - Tempo (double start_npm, double type, double end_npm) - : _note_types_per_minute (start_npm), _note_type (type), _end_note_types_per_minute (end_npm) {} - - double note_types_per_minute () const { return _note_types_per_minute; } - double note_types_per_minute (double note_type) const { return (_note_types_per_minute / _note_type) * note_type; } - void set_note_types_per_minute (double npm) { _note_types_per_minute = npm; } - double note_type () const { return _note_type; } - - double quarter_notes_per_minute () const { return note_types_per_minute (4.0); } - double pulses_per_minute () const { return note_types_per_minute (1.0); } - - double end_note_types_per_minute () const { return _end_note_types_per_minute; } - double end_note_types_per_minute (double note_type) const { return (_end_note_types_per_minute / _note_type) * note_type; } - void set_end_note_types_per_minute (double npm) { _end_note_types_per_minute = npm; } - - double end_quarter_notes_per_minute () const { return end_note_types_per_minute (4.0); } - double end_pulses_per_minute () const { return end_note_types_per_minute (1.0); } - - /** audio samples per note type. - * if you want an instantaneous value for this, use TempoMap::samples_per_quarter_note_at() instead. - * @param sr samplerate - */ - double samples_per_note_type (samplecnt_t sr) const { - return (60.0 * sr) / _note_types_per_minute; - } - /** audio samples per quarter note. - * if you want an instantaneous value for this, use TempoMap::samples_per_quarter_note_at() instead. - * @param sr samplerate - */ - double samples_per_quarter_note (samplecnt_t sr) const { - return (60.0 * sr) / quarter_notes_per_minute (); - } - - protected: - double _note_types_per_minute; - double _note_type; - double _end_note_types_per_minute; -}; - -/** Meter, or time signature (beats per bar, and which note type is a beat). */ -class LIBARDOUR_API Meter { - public: - Meter (double dpb, double bt) - : _divisions_per_bar (dpb), _note_type (bt) {} - - double divisions_per_bar () const { return _divisions_per_bar; } - double note_divisor() const { return _note_type; } - - double samples_per_bar (const Tempo&, samplecnt_t sr) const; - double samples_per_grid (const Tempo&, samplecnt_t sr) const; - - inline bool operator==(const Meter& other) - { return _divisions_per_bar == other.divisions_per_bar() && _note_type == other.note_divisor(); } - - protected: - /** The number of divisions in a bar. This is a floating point value because - there are musical traditions on our planet that do not limit - themselves to integral numbers of beats per bar. - */ - double _divisions_per_bar; - - /** The type of "note" that a division represents. For example, 4.0 is - a quarter (crotchet) note, 8.0 is an eighth (quaver) note, etc. - */ - double _note_type; -}; - -/** A section of timeline with a certain Tempo or Meter. */ -class LIBARDOUR_API MetricSection { - public: - MetricSection (double pulse, double minute, PositionLockStyle pls, bool is_tempo, samplecnt_t sample_rate) - : _pulse (pulse), _minute (minute), _initial (false), _position_lock_style (pls), _is_tempo (is_tempo), _sample_rate (sample_rate) {} - - virtual ~MetricSection() {} - - const double& pulse () const { return _pulse; } - void set_pulse (double pulse) { _pulse = pulse; } - - double minute() const { return _minute; } - virtual void set_minute (double m) { - _minute = m; - } - - samplepos_t sample () const { return sample_at_minute (_minute); } - - void set_initial (bool yn) { _initial = yn; } - bool initial() const { return _initial; } - - /* MeterSections are not stateful in the full sense, - but we do want them to control their own - XML state information. - */ - virtual XMLNode& get_state() const = 0; - - virtual int set_state (const XMLNode&, int version); - - PositionLockStyle position_lock_style () const { return _position_lock_style; } - void set_position_lock_style (PositionLockStyle ps) { _position_lock_style = ps; } - bool is_tempo () const { return _is_tempo; } - - samplepos_t sample_at_minute (const double& time) const; - double minute_at_sample (const samplepos_t sample) const; - -protected: - void add_state_to_node (XMLNode& node) const; - -private: - - double _pulse; - double _minute; - bool _initial; - PositionLockStyle _position_lock_style; - const bool _is_tempo; - samplecnt_t _sample_rate; -}; - -/** A section of timeline with a certain Meter. */ -class LIBARDOUR_API MeterSection : public MetricSection, public Meter { - public: - MeterSection (double pulse, double minute, double beat, const Temporal::BBT_Time& bbt, double bpb, double note_type, PositionLockStyle pls, samplecnt_t sr) - : MetricSection (pulse, minute, pls, false, sr), Meter (bpb, note_type), _bbt (bbt), _beat (beat) {} - - MeterSection (const XMLNode&, const samplecnt_t sample_rate); - - static const std::string xml_state_node_name; - - XMLNode& get_state() const; - - void set_beat (std::pair& w) { - _beat = w.first; - _bbt = w.second; - } - - const Temporal::BBT_Time& bbt() const { return _bbt; } - const double& beat () const { return _beat; } - void set_beat (double beat) { _beat = beat; } - -private: - Temporal::BBT_Time _bbt; - double _beat; -}; - -/** A section of timeline with a certain Tempo. */ -class LIBARDOUR_API TempoSection : public MetricSection, public Tempo { - public: - enum Type { - Ramp, - Constant, - }; - - TempoSection (const double& pulse, const double& minute, Tempo tempo, PositionLockStyle pls, samplecnt_t sr) - : MetricSection (pulse, minute, pls, true, sr), Tempo (tempo), _c (0.0), _active (true), _locked_to_meter (false), _clamped (false) {} - - TempoSection (const XMLNode&, const samplecnt_t sample_rate); - - static const std::string xml_state_node_name; - - XMLNode& get_state() const; - - double c () const { return _c; } - void set_c (double c) { _c = c; } - - Type type () const { if (note_types_per_minute() == end_note_types_per_minute()) { return Constant; } else { return Ramp; } } - - bool active () const { return _active; } - void set_active (bool yn) { _active = yn; } - - bool locked_to_meter () const { return _locked_to_meter; } - void set_locked_to_meter (bool yn) { _locked_to_meter = yn; } - - bool clamped () const { return _clamped; } - void set_clamped (bool yn) { _clamped = yn; } - - Tempo tempo_at_minute (const double& minute) const; - double minute_at_ntpm (const double& ntpm, const double& pulse) const; - - Tempo tempo_at_pulse (const double& pulse) const; - double pulse_at_ntpm (const double& ntpm, const double& minute) const; - - double pulse_at_minute (const double& minute) const; - double minute_at_pulse (const double& pulse) const; - - double compute_c_pulse (const double& end_ntpm, const double& end_pulse) const; - double compute_c_minute (const double& end_ntpm, const double& end_minute) const; - - double pulse_at_sample (const samplepos_t sample) const; - samplepos_t sample_at_pulse (const double& pulse) const; - - Temporal::BBT_Time legacy_bbt () { return _legacy_bbt; } - - private: - - /* tempo ramp functions. zero-based with time in minutes, - * 'tick tempo' in ticks per minute and tempo in bpm. - * time relative to section start. - */ - double a_func (double end_tpm, double c_func) const; - double c_func (double end_tpm, double end_time) const; - - double _tempo_at_time (const double& time) const; - double _time_at_tempo (const double& tempo) const; - - double _tempo_at_pulse (const double& pulse) const; - double _pulse_at_tempo (const double& tempo) const; - - double _pulse_at_time (const double& time) const; - double _time_at_pulse (const double& pulse) const; - - /* this value provides a fractional offset into the bar in which - the tempo section is located in. A value of 0.0 indicates that - it occurs on the first beat of the bar, a value of 0.5 indicates - that it occurs halfway through the bar and so on. - - this enables us to keep the tempo change at the same relative - position within the bar if/when the meter changes. - */ - - double _c; - bool _active; - bool _locked_to_meter; - bool _clamped; - Temporal::BBT_Time _legacy_bbt; -}; - -typedef std::list Metrics; - -/** Helper class to keep track of the Meter *AND* Tempo in effect - at a given point in time. -*/ -class LIBARDOUR_API TempoMetric { - public: - TempoMetric (const Meter& m, const Tempo& t) - : _meter (&m), _tempo (&t), _minute (0.0), _pulse (0.0) {} - - void set_tempo (const Tempo& t) { _tempo = &t; } - void set_meter (const Meter& m) { _meter = &m; } - void set_minute (double m) { _minute = m; } - void set_pulse (const double& p) { _pulse = p; } - - void set_metric (const MetricSection* section) { - const MeterSection* meter; - const TempoSection* tempo; - if ((meter = dynamic_cast(section))) { - set_meter(*meter); - } else if ((tempo = dynamic_cast(section))) { - set_tempo(*tempo); - } - - set_minute (section->minute()); - set_pulse (section->pulse()); - } - - const Meter& meter() const { return *_meter; } - const Tempo& tempo() const { return *_tempo; } - double minute() const { return _minute; } - const double& pulse() const { return _pulse; } - - private: - const Meter* _meter; - const Tempo* _tempo; - double _minute; - double _pulse; -}; - -/** Tempo Map - mapping of timecode to musical time. - * convert audio-samples, sample-rate to Bar/Beat/Tick, Meter/Tempo - */ -class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible -{ - public: - TempoMap (samplecnt_t sample_rate); - ~TempoMap(); - - TempoMap& operator= (TempoMap const &); - - /* measure-based stuff */ - - enum BBTPointType { - Bar, - Beat, - }; - - struct BBTPoint { - Meter meter; - Tempo tempo; - samplepos_t sample; - uint32_t bar; - uint32_t beat; - double qn; - - BBTPoint (const MeterSection& m, const Tempo& t, samplepos_t f, - uint32_t b, uint32_t e, double qnote) - : meter (m), tempo (t), sample (f), bar (b), beat (e), qn (qnote) {} - - Temporal::BBT_Time bbt() const { return Temporal::BBT_Time (bar, beat, 0); } - operator Temporal::BBT_Time() const { return bbt(); } - operator samplepos_t() const { return sample; } - bool is_bar() const { return beat == 1; } - }; - - template void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) { - Glib::Threads::RWLock::ReaderLock lm (lock); - (obj.*method)(_metrics); - } - - void get_grid (std::vector&, - samplepos_t start, samplepos_t end, uint32_t bar_mod = 0); - - void midi_clock_beat_at_of_after (samplepos_t const pos, samplepos_t& clk_pos, uint32_t& clk_beat); - - static const Tempo& default_tempo() { return _default_tempo; } - static const Meter& default_meter() { return _default_meter; } - - /* because tempi may be ramped, this is only valid for the instant requested.*/ - double samples_per_quarter_note_at (const samplepos_t, const samplecnt_t sr) const; - - const TempoSection& tempo_section_at_sample (samplepos_t sample) const; - TempoSection& tempo_section_at_sample (samplepos_t sample); - const MeterSection& meter_section_at_sample (samplepos_t sample) const; - const MeterSection& meter_section_at_beat (double beat) const; - - TempoSection* previous_tempo_section (TempoSection*) const; - TempoSection* next_tempo_section (TempoSection*) const; - - /** add a tempo section locked to pls. ignored values will be set in recompute_tempi() - * @param pulse pulse position of new section. ignored if \p pls == AudioTime - * @param sample frame position of new section. ignored if \p pls == MusicTime - * @param pls the position lock style - */ - TempoSection* add_tempo (const Tempo&, const double& pulse, const samplepos_t sample, PositionLockStyle pls); - - /** add a meter section locked to \p pls . ignored values will be set in recompute_meters() - * @param meter the Meter to be added - * @param where bbt position of new section - * @param sample frame position of new section. ignored if \p pls == MusicTime - * - * note that \p sample may also be ignored if it would create an un-solvable map - * (previous audio-locked tempi may place the requested beat at an earlier time than sample) - * in which case the new meter will be placed at the specified BBT. - * @param pls the position lock style - * - * adding an audio-locked meter will add a meter-locked tempo section at the meter position. - * the meter-locked tempo tempo will be the Tempo at the beat - */ - MeterSection* add_meter (const Meter& meter, const Temporal::BBT_Time& where, samplepos_t sample, PositionLockStyle pls); - - void remove_tempo (const TempoSection&, bool send_signal); - void remove_meter (const MeterSection&, bool send_signal); - - void replace_tempo (TempoSection&, const Tempo&, const double& pulse, const samplepos_t sample, PositionLockStyle pls); - - void replace_meter (const MeterSection&, const Meter&, const Temporal::BBT_Time& where, samplepos_t sample, PositionLockStyle pls); - - MusicSample round_to_bar (samplepos_t sample, Temporal::RoundMode dir); - MusicSample round_to_beat (samplepos_t sample, Temporal::RoundMode dir); - MusicSample round_to_quarter_note_subdivision (samplepos_t fr, int sub_num, Temporal::RoundMode dir); - - void set_length (samplepos_t samples); - - XMLNode& get_state (void); - int set_state (const XMLNode&, int version); - - void dump (std::ostream&) const; - void clear (); - - TempoMetric metric_at (Temporal::BBT_Time bbt) const; - - /** Return the TempoMetric at sample @p t, and point @p last to the latest - * metric change <= t, if it is non-NULL. - */ - TempoMetric metric_at (samplepos_t, Metrics::const_iterator* last=NULL) const; - - Metrics::const_iterator metrics_end() { return _metrics.end(); } - - void change_existing_tempo_at (samplepos_t, double bpm, double note_type, double end_ntpm); - void change_initial_tempo (double ntpm, double note_type, double end_ntpm); - - void insert_time (samplepos_t, samplecnt_t); - bool remove_time (samplepos_t where, samplecnt_t amount); //returns true if anything was moved - - int n_tempos () const; - int n_meters () const; - - samplecnt_t sample_rate () const { return _sample_rate; } - - /* TEMPO- AND METER-SENSITIVE FUNCTIONS - - bbt_at_sample(), sample_at_bbt(), beat_at_sample(), sample_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 Temporal::Beats. - */ - - double beat_at_sample (const samplecnt_t sample) const; - samplepos_t sample_at_beat (const double& beat) const; - - const Meter& meter_at_sample (samplepos_t) const; - - /* bbt - it's nearly always better to use meter-based beat (above) - unless tick resolution is desirable. - */ - Temporal::BBT_Time bbt_at_sample (samplepos_t when); - Temporal::BBT_Time bbt_at_sample_rt (samplepos_t when) const; - samplepos_t sample_at_bbt (const Temporal::BBT_Time&); - - double beat_at_bbt (const Temporal::BBT_Time& bbt); - Temporal::BBT_Time bbt_at_beat (const double& beats); - - double quarter_note_at_bbt (const Temporal::BBT_Time& bbt); - double quarter_note_at_bbt_rt (const Temporal::BBT_Time& bbt); - Temporal::BBT_Time bbt_at_quarter_note (const double& quarter_note); - - samplecnt_t bbt_duration_at (samplepos_t, const Temporal::BBT_Time&, int dir); - samplepos_t samplepos_plus_bbt (samplepos_t pos, Temporal::BBT_Time b) const; - - /* TEMPO-SENSITIVE FUNCTIONS - - These next 2 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 Temporal::Beats. - */ - - samplepos_t samplepos_plus_qn (samplepos_t, Temporal::Beats) const; - Temporal::Beats framewalk_to_qn (samplepos_t pos, samplecnt_t distance) const; - - /* quarter note related functions are also tempo-sensitive and ignore meter. - quarter notes may be compared with and assigned to Temporal::Beats. - */ - double quarter_note_at_sample (const samplepos_t sample) const; - double quarter_note_at_sample_rt (const samplepos_t sample) const; - samplepos_t sample_at_quarter_note (const double quarter_note) const; - - samplecnt_t samples_between_quarter_notes (const double start, const double end) const; - double quarter_notes_between_samples (const samplecnt_t start, const samplecnt_t end) const; - - double quarter_note_at_beat (const double beat) const; - double beat_at_quarter_note (const double beat) const; - - /* obtain a musical subdivision via a sample position and magic note divisor.*/ - double exact_qn_at_sample (const samplepos_t sample, const int32_t sub_num) const; - double exact_beat_at_sample (const samplepos_t sample, const int32_t sub_num) const; - - Tempo tempo_at_sample (const samplepos_t sample) const; - samplepos_t sample_at_tempo (const Tempo& tempo) const; - Tempo tempo_at_quarter_note (const double& beat) const; - double quarter_note_at_tempo (const Tempo& tempo) const; - - void gui_set_tempo_position (TempoSection*, const samplepos_t sample, const int& sub_num); - void gui_set_meter_position (MeterSection*, const samplepos_t sample); - bool gui_change_tempo (TempoSection*, const Tempo& bpm); - void gui_stretch_tempo (TempoSection* tempo, const samplepos_t sample, const samplepos_t end_sample, const double start_qnote, const double end_qnote); - void gui_stretch_tempo_end (TempoSection* tempo, const samplepos_t sample, const samplepos_t end_sample); - bool gui_twist_tempi (TempoSection* first, const Tempo& bpm, const samplepos_t sample, const samplepos_t end_sample); - - std::pair predict_tempo_position (TempoSection* section, const Temporal::BBT_Time& bbt); - bool can_solve_bbt (TempoSection* section, const Temporal::BBT_Time& bbt); - - PBD::Signal1 MetricPositionChanged; - void fix_legacy_session(); - void fix_legacy_end_session(); - - samplepos_t music_origin (); - -private: - /* prevent copy construction */ - TempoMap (TempoMap const&); - - TempoSection* previous_tempo_section_locked (const Metrics& metrics, TempoSection*) const; - TempoSection* next_tempo_section_locked (const Metrics& metrics, TempoSection*) const; - - double beat_at_minute_locked (const Metrics& metrics, const double& minute) const; - double minute_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_minute_locked (const Metrics& metrics, const double& minute) const; - double minute_at_pulse_locked (const Metrics& metrics, const double& pulse) const; - - Tempo tempo_at_minute_locked (const Metrics& metrics, const double& minute) const; - double minute_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const; - - Tempo tempo_at_pulse_locked (const Metrics& metrics, const double& pulse) const; - double pulse_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) const; - - Temporal::BBT_Time bbt_at_minute_locked (const Metrics& metrics, const double& minute) const; - double minute_at_bbt_locked (const Metrics& metrics, const Temporal::BBT_Time&) const; - - double beat_at_bbt_locked (const Metrics& metrics, const Temporal::BBT_Time& bbt) const ; - Temporal::BBT_Time bbt_at_beat_locked (const Metrics& metrics, const double& beats) const; - - double pulse_at_bbt_locked (const Metrics& metrics, const Temporal::BBT_Time& bbt) const; - Temporal::BBT_Time bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const; - - double minutes_between_quarter_notes_locked (const Metrics& metrics, const double start_qn, const double end_qn) const; - double quarter_notes_between_samples_locked (const Metrics& metrics, const samplecnt_t start, const samplecnt_t end) const; - - const TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute) const; - TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute); - const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const; - - const MeterSection& meter_section_at_minute_locked (const Metrics& metrics, double minute) 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_tempi (const Metrics& metrics, const samplepos_t sample); - - bool solve_map_minute (Metrics& metrics, TempoSection* section, const double& minute); - bool solve_map_pulse (Metrics& metrics, TempoSection* section, const double& pulse); - bool solve_map_minute (Metrics& metrics, MeterSection* section, const double& minute); - bool solve_map_bbt (Metrics& metrics, MeterSection* section, const Temporal::BBT_Time& bbt); - - double exact_beat_at_sample_locked (const Metrics& metrics, const samplepos_t sample, const int32_t sub_num) const; - double exact_qn_at_sample_locked (const Metrics& metrics, const samplepos_t sample, const int32_t sub_num) const; - - double minute_at_sample (const samplepos_t sample) const; - samplepos_t sample_at_minute (const double minute) const; - - friend class ::BBTTest; - friend class ::FrameposPlusBeatsTest; - friend class ::FrameposMinusBeatsTest; - friend class ::TempoTest; - - static Tempo _default_tempo; - static Meter _default_meter; - - Metrics _metrics; - samplecnt_t _sample_rate; - mutable Glib::Threads::RWLock lock; - - void recompute_tempi (Metrics& metrics); - void recompute_meters (Metrics& metrics); - void recompute_map (Metrics& metrics, samplepos_t end = -1); - - MusicSample round_to_type (samplepos_t fr, Temporal::RoundMode dir, BBTPointType); - - const MeterSection& first_meter() const; - MeterSection& first_meter(); - const TempoSection& first_tempo() const; - TempoSection& first_tempo(); - - void do_insert (MetricSection* section); - - TempoSection* add_tempo_locked (const Tempo&, double pulse, double minute - , PositionLockStyle pls, bool recompute, bool locked_to_meter = false, bool clamped = false); - - MeterSection* add_meter_locked (const Meter&, const Temporal::BBT_Time& where, samplepos_t sample, PositionLockStyle pls, bool recompute); - - bool remove_tempo_locked (const TempoSection&); - bool remove_meter_locked (const MeterSection&); - - TempoSection* copy_metrics_and_point (const Metrics& metrics, Metrics& copy, TempoSection* section) const; - MeterSection* copy_metrics_and_point (const Metrics& metrics, Metrics& copy, MeterSection* section) const; -}; - -}; /* namespace ARDOUR */ - -LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::Meter&); -LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::Tempo&); -LIBARDOUR_API std::ostream& operator<< (std::ostream&, const ARDOUR::MetricSection&); - -namespace PBD { - DEFINE_ENUM_CONVERT (ARDOUR::TempoSection::Type) -} +#include "temporal/tempo.h" #endif /* __ardour_tempo_h__ */ diff --git a/libs/ardour/ardour/transport_master.h b/libs/ardour/ardour/transport_master.h index 595dceb068..736568d0c3 100644 --- a/libs/ardour/ardour/transport_master.h +++ b/libs/ardour/ardour/transport_master.h @@ -44,7 +44,6 @@ namespace ARDOUR { -class TempoMap; class Session; class AudioEngine; class Location; diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index 8090ad0110..79e0682b95 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -115,8 +115,6 @@ setup_enum_writer () Source::Flag _Source_Flag; DiskIOProcessor::Flag _DiskIOProcessor_Flag; Location::Flags _Location_Flags; - PositionLockStyle _PositionLockStyle; - TempoSection::Type _TempoSection_Type; Track::FreezeState _Track_FreezeState; AutomationList::InterpolationStyle _AutomationList_InterpolationStyle; AnyTime::Type _AnyTime_Type; @@ -568,10 +566,6 @@ setup_enum_writer () REGISTER_CLASS_ENUM (Location, IsClockOrigin); REGISTER_BITS (_Location_Flags); - REGISTER_CLASS_ENUM (TempoSection, Ramp); - REGISTER_CLASS_ENUM (TempoSection, Constant); - REGISTER (_TempoSection_Type); - REGISTER_CLASS_ENUM (Track, NoFreeze); REGISTER_CLASS_ENUM (Track, Frozen); REGISTER_CLASS_ENUM (Track, UnFrozen); @@ -736,10 +730,6 @@ setup_enum_writer () REGISTER_ENUM(InhibitAlways); REGISTER(_ScreenSaverMode); - REGISTER_ENUM(AudioTime); - REGISTER_ENUM(MusicTime); - REGISTER(_PositionLockStyle); - REGISTER_ENUM (Small); REGISTER_ENUM (Medium); REGISTER_ENUM (Large); diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index 9dacc1e0b5..8a527a70fd 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -354,6 +354,7 @@ CLASSKEYS(LuaDialog::ProgressWindow); */ using namespace ARDOUR; +using namespace Temporal; /** Access libardour global configuration */ static RCConfiguration* _libardour_config () { @@ -1866,63 +1867,35 @@ LuaBindings::common (lua_State* L) .beginClass ("Tempo") .addConstructor () - .addFunction ("note_type", &Tempo::note_type) - .addFunction ("note_types_per_minute", (double (Tempo::*)() const)&Tempo::note_types_per_minute) - .addFunction ("end_note_types_per_minute", (double (Tempo::*)() const)&Tempo::end_note_types_per_minute) - .addFunction ("quarter_notes_per_minute", &Tempo::quarter_notes_per_minute) - .addFunction ("samples_per_quarter_note", &Tempo::samples_per_quarter_note) - .addFunction ("samples_per_note_type", &Tempo::samples_per_note_type) + .addFunction ("note_type", &Temporal::Tempo::note_type) + .addFunction ("note_types_per_minute", (double (Temporal::Tempo::*)() const)&Temporal::Tempo::note_types_per_minute) + .addFunction ("quarter_notes_per_minute", &Temporal::Tempo::quarter_notes_per_minute) + .addFunction ("samples_per_quarter_note", &Temporal::Tempo::samples_per_quarter_note) + .addFunction ("samples_per_note_type", &Temporal::Tempo::samples_per_note_type) .endClass () .beginClass ("Meter") .addConstructor () .addFunction ("divisions_per_bar", &Meter::divisions_per_bar) - .addFunction ("note_divisor", &Meter::note_divisor) - .addFunction ("samples_per_bar", &Meter::samples_per_bar) - .addFunction ("samples_per_grid", &Meter::samples_per_grid) + .addFunction ("note_value", &Meter::note_value) .endClass () +#warning NUTEMPO need to consider which methods to use here since ::add_* are private right now and many others have changed +#if 0 .beginClass ("TempoMap") .addFunction ("add_tempo", &TempoMap::add_tempo) .addFunction ("add_meter", &TempoMap::add_meter) - .addFunction ("tempo_section_at_sample", (TempoSection& (TempoMap::*)(samplepos_t))&TempoMap::tempo_section_at_sample) - .addFunction ("meter_section_at_sample", &TempoMap::meter_section_at_sample) + .addFunction ("tempo_section_at_frame", (TempoSection& (TempoMap::*)(samplepos_t))&TempoMap::tempo_section_at_sample) + .addFunction ("tempo_section_at_frame", (const TempoSection& (TempoMap::*)(samplepos_t) const)&TempoMap::tempo_section_at_sample) + .addFunction ("meter_section_at_frame", &TempoMap::meter_section_at_sample) .addFunction ("meter_section_at_beat", &TempoMap::meter_section_at_beat) - .addFunction ("bbt_at_sample", &TempoMap::bbt_at_sample) - .addFunction ("exact_beat_at_sample", &TempoMap::exact_beat_at_sample) - .addFunction ("exact_qn_at_sample", &TempoMap::exact_qn_at_sample) + .addFunction ("bbt_at_frame", &TempoMap::bbt_at_sample) + .addFunction ("exact_beat_at_frame", &TempoMap::exact_beat_at_sample) + .addFunction ("exact_qn_at_frame", &TempoMap::exact_qn_at_sample) .addFunction ("samplepos_plus_qn", &TempoMap::samplepos_plus_qn) .addFunction ("framewalk_to_qn", &TempoMap::framewalk_to_qn) - .addFunction ("previous_tempo_section", &TempoMap::previous_tempo_section) - .addFunction ("next_tempo_section", &TempoMap::next_tempo_section) .endClass () - - .beginClass ("MetricSection") - .addFunction ("pulse", &MetricSection::pulse) - .addFunction ("set_pulse", &MetricSection::set_pulse) - .addFunction ("sample", &MetricSection::sample) - .addFunction ("minute", &MetricSection::minute) - .addFunction ("initial", &MetricSection::initial) - .addFunction ("is_tempo", &MetricSection::is_tempo) - .addFunction ("sample_at_minute", &MetricSection::sample_at_minute) - .addFunction ("minute_at_sample", &MetricSection::minute_at_sample) - .endClass () - - .deriveClass ("TempoSection") - .addCast ("to_tempo") - .addFunction ("c", (double(TempoSection::*)()const)&TempoSection::c) - .addFunction ("active", &TempoSection::active) - .addFunction ("locked_to_meter", &TempoSection::locked_to_meter) - .addFunction ("clamped", &TempoSection::clamped) - .endClass () - - .deriveClass ("MeterSection") - .addCast ("to_meter") - .addFunction ("bbt", &MeterSection::bbt) - .addFunction ("beat", &MeterSection::beat) - .addFunction ("set_beat", (void(MeterSection::*)(double))&MeterSection::set_beat) - .endClass () - +#endif .beginClass ("ChanCount") .addConstructor () .addFunction ("get", &ChanCount::get) @@ -2099,19 +2072,25 @@ LuaBindings::common (lua_State* L) .addConst ("SyncPoint", ARDOUR::RegionPoint(SyncPoint)) .endNamespace () +#warning NUTEMPO add timeline types here instead +#if 0 .beginNamespace ("TempoSection") .beginNamespace ("PositionLockStyle") .addConst ("AudioTime", ARDOUR::PositionLockStyle(AudioTime)) .addConst ("MusicTime", ARDOUR::PositionLockStyle(MusicTime)) .endNamespace () .endNamespace () +#endif +#warning NUTEMPO fix types here +#if 0 .beginNamespace ("TempoSection") .beginNamespace ("Type") .addConst ("Ramp", ARDOUR::TempoSection::Type(TempoSection::Ramp)) .addConst ("Constant", ARDOUR::TempoSection::Type(TempoSection::Constant)) .endNamespace () .endNamespace () +#endif .beginNamespace ("TrackMode") .addConst ("Normal", ARDOUR::TrackMode(Start)) diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 0e76991779..2be7b042c2 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -127,6 +127,7 @@ static const size_t NBUFS = 4; using namespace std; using namespace ARDOUR; using namespace PBD; +using namespace Temporal; bool LV2Plugin::force_state_save = false; int32_t LV2Plugin::_ui_style_flat = 0; @@ -2573,7 +2574,7 @@ static bool write_position(LV2_Atom_Forge* forge, LV2_Evbuf* buf, const TempoMetric& t, - Temporal::BBT_Time& bbt, + BBT_Time& bbt, double speed, double time_scale, double bpm, @@ -2596,7 +2597,7 @@ write_position(LV2_Atom_Forge* forge, lv2_atom_forge_key(forge, urids.time_bar); lv2_atom_forge_long(forge, bbt.bars - 1); lv2_atom_forge_key(forge, urids.time_beatUnit); - lv2_atom_forge_int(forge, t.meter().note_divisor()); + lv2_atom_forge_int(forge, t.meter().note_value()); lv2_atom_forge_key(forge, urids.time_beatsPerBar); lv2_atom_forge_float(forge, t.meter().divisions_per_bar()); lv2_atom_forge_key(forge, urids.time_beatsPerMinute); @@ -2653,7 +2654,15 @@ LV2Plugin::connect_and_run(BufferSet& bufs, } if (_bpm_control_port) { + float bpm = tmap.tempo_at_sample (start0).note_types_per_minute(); + TempoMapPoints tempo_map_points; + tmap.get_grid (tempo_map_points, start, end, 0); + TempoMapPoint first_tempo_map_point = tempo_map_points.front(); + + /* note that this is not necessarily quarter notes */ + const double bpm = first_tempo_map_point.tempo().note_types_per_minute(); + if (*_bpm_control_port != bpm) { AutomationCtrlPtr c = get_automation_control (_bpm_control_port_index); if (c && c->ac) { @@ -2661,6 +2670,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, c->ac->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */ } } + *_bpm_control_port = bpm; } @@ -2735,14 +2745,14 @@ LV2Plugin::connect_and_run(BufferSet& bufs, if (valid && (flags & PORT_INPUT)) { if ((flags & PORT_POSITION)) { - - Temporal::BBT_Time bbt (tmap.bbt_at_sample (start0)); + const Temporal::TempoMetric& metric (tmap.metric_at (start0)); + Temporal::BBT_Time bbt (metric.bbt_at (start0)); double time_scale = Port::speed_ratio (); - double bpm = tmap.tempo_at_sample (start0).note_types_per_minute(); - double beatpos = (bbt.bars - 1) * tmetric.meter().divisions_per_bar() + double bpm = metric.tempo().note_types_per_minute(); + double beatpos = (bbt.bars - 1) * metric.meter().divisions_per_bar() + (bbt.beats - 1) + (bbt.ticks / Temporal::ticks_per_beat); - beatpos *= tmetric.meter().note_divisor() / 4.0; + beatpos *= metric.note_value() / 4.0; if (start != _next_cycle_start || speed != _next_cycle_speed || time_scale != _prev_time_scale || @@ -2750,7 +2760,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, bpm != _current_bpm) { // Transport or Tempo has changed, write position at cycle start write_position(&_impl->forge, _ev_buffers[port_index], - tmetric, bbt, speed, time_scale, bpm, start, 0); + metric, bbt, speed, time_scale, bpm, start, 0); } } @@ -2766,10 +2776,11 @@ LV2Plugin::connect_and_run(BufferSet& bufs, const uint32_t type = _uri_map.urids.midi_MidiEvent; const samplepos_t tend = end; ++metric_i; - while (m != m_end || (metric_i != tmap.metrics_end() && - (*metric_i)->sample() < tend)) { - MetricSection* metric = (metric_i != tmap.metrics_end()) - ? *metric_i : NULL; + + while (m != m_end || (metric_i != tmap.metrics_end() && (*metric_i)->sample() < tend)) { + + MetricSection* metric = (metric_i != tmap.metrics_end()) ? *metric_i : NULL; + if (m != m_end && (!metric || metric->sample() > (*m).time())) { const Evoral::Event ev(*m, false); if (ev.time() < nframes) { @@ -2779,12 +2790,11 @@ LV2Plugin::connect_and_run(BufferSet& bufs, ++m; } else { assert (metric); - tmetric.set_metric(metric); - Temporal::BBT_Time bbt; - bbt = tmap.bbt_at_sample (metric->sample()); - double bpm = tmap.tempo_at_sample (start0 /*XXX metric->sample() */).note_types_per_minute(); + bbt = metric.bbt(); + double bpm = metric.tempo().note_types_per_minute(); + write_position(&_impl->forge, _ev_buffers[port_index], - tmetric, bbt, speed, Port::speed_ratio (), + metric, bbt, speed, Port::speed_ratio (), bpm, metric->sample(), metric->sample() - start0); ++metric_i; diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc index b76182f1fb..18fdd1472d 100644 --- a/libs/ardour/midi_clock_slave.cc +++ b/libs/ardour/midi_clock_slave.cc @@ -157,7 +157,8 @@ MIDIClock_TransportMaster::pre_process (MIDI::pframes_t nframes, samplepos_t now void MIDIClock_TransportMaster::calculate_one_ppqn_in_samples_at(samplepos_t time) { - const double samples_per_quarter_note = _session->tempo_map().samples_per_quarter_note_at (time, ENGINE->sample_rate()); + const Temporal::TempoMetric& metric = _session->tempo_map().metric_at (time); + const double samples_per_quarter_note = metric.tempo().samples_per_quarter_note (ENGINE->sample_rate()); one_ppqn_in_samples = samples_per_quarter_note / double (ppqn); // DEBUG_TRACE (DEBUG::MidiClock, string_compose ("at %1, one ppqn = %2 [spl] spqn = %3, ppqn = %4\n", time, one_ppqn_in_samples, samples_per_quarter_note, ppqn)); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 91e18f9f70..9cf262250b 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -144,6 +144,7 @@ class Speakers; using namespace std; using namespace ARDOUR; using namespace PBD; +using namespace Temporal; bool Session::_disable_all_loaded_plugins = false; bool Session::_bypass_all_loaded_plugins = false; @@ -2194,9 +2195,8 @@ Session::preroll_samples (samplepos_t pos) const { const float pr = Config->get_preroll_seconds(); if (pos >= 0 && pr < 0) { - const Tempo& tempo = _tempo_map->tempo_at_sample (pos); - const Meter& meter = _tempo_map->meter_at_sample (pos); - return meter.samples_per_bar (tempo, sample_rate()) * -pr; + Temporal::TempoMetric const & metric (_tempo_map->metric_at (pos)); + return metric.samples_per_bar (sample_rate()) * -pr; } if (pr < 0) { return 0; @@ -5545,7 +5545,7 @@ Session::available_capture_duration () } void -Session::tempo_map_changed (const PropertyChange&) +Session::tempo_map_changed () { clear_clicks (); @@ -7428,10 +7428,9 @@ void Session::maybe_update_tempo_from_midiclock_tempo (float bpm) { if (_tempo_map->n_tempos() == 1) { - TempoSection& ts (_tempo_map->tempo_section_at_sample (0)); - if (fabs (ts.note_types_per_minute() - bpm) > (0.01 * ts.note_types_per_minute())) { - const Tempo tempo (bpm, 4.0, bpm); - _tempo_map->replace_tempo (ts, tempo, 0.0, 0.0, AudioTime); + Temporal::TempoMetric const & metric (_tempo_map->metric_at (0)); + if (fabs (metric.tempo().note_types_per_minute() - bpm) > (0.01 * metric.tempo().note_types_per_minute())) { + _tempo_map->change_tempo (metric.tempo(), Tempo (bpm, 4.0, bpm)); } } } diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc index a474c87175..0953482317 100644 --- a/libs/ardour/session_click.cc +++ b/libs/ardour/session_click.cc @@ -38,6 +38,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; +using namespace Temporal; Pool Click::pool ("click", sizeof (Click), 1024); @@ -48,7 +49,7 @@ Pool Click::pool ("click", sizeof (Click), 1024); * (session.h does not include tempo.h so making this * a Session member variable is tricky.) */ -static vector _click_points; +static TempoMapPoints _click_points; void Session::add_click (samplepos_t pos, bool emphasis) @@ -123,7 +124,7 @@ Session::click (samplepos_t cycle_start, samplecnt_t nframes) const samplepos_t end = start + move; _click_points.clear (); - _tempo_map->get_grid (_click_points, start, end); + _tempo_map->get_grid (_click_points, samples_to_superclock (start, sample_rate()), samples_to_superclock (end, sample_rate())); if (distance (_click_points.begin(), _click_points.end()) == 0) { start += move; @@ -131,17 +132,14 @@ Session::click (samplepos_t cycle_start, samplecnt_t nframes) continue; } - for (vector::iterator i = _click_points.begin(); i != _click_points.end(); ++i) { - assert ((*i).sample >= start && (*i).sample < end); - switch ((*i).beat) { - case 1: - add_click ((*i).sample, true); - break; - default: - if (click_emphasis_data == 0 || (Config->get_use_click_emphasis () == false) || (click_emphasis_data && (*i).beat != 1)) { // XXX why is this check needed ?? (*i).beat !=1 must be true here - add_click ((*i).sample, false); - } - break; + for (TempoMapPoints::iterator i = _click_points.begin(); i != _click_points.end(); ++i) { + + assert (superclock_to_samples ((*i).sclock(), sample_rate()) >= start && superclock_to_samples ((*i).sclock(), sample_rate()) < end); + + if (i->bbt().is_bar() && (click_emphasis_data && Config->get_use_click_emphasis())) { + add_click ((*i).sclock(), true); + } else { + add_click ((*i).sclock(), false); } } @@ -313,7 +311,6 @@ Session::setup_click_sounds (Sample** data, Sample const * default_data, samplec void Session::setup_click_sounds (int which) { - _click_points.reserve (8); clear_clicks (); if (which == 0 || which == 1) { diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc index 44bacd2409..1bc38b3d20 100644 --- a/libs/ardour/session_command.cc +++ b/libs/ardour/session_command.cc @@ -45,6 +45,7 @@ class Command; using namespace PBD; using namespace ARDOUR; +using namespace Temporal; #include "pbd/i18n.h" diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 6c36ce6adc..5921dd5174 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -263,9 +263,8 @@ Session::post_engine_init () /* tempo map requires sample rate knowledge */ delete _tempo_map; - _tempo_map = new TempoMap (_current_sample_rate); - _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1)); - _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1)); + _tempo_map = new Temporal::TempoMap (Temporal::Tempo (120), Temporal::Meter (4, 4), _current_sample_rate); + _tempo_map->Changed.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this)); } catch (std::exception const & e) { error << _("Unexpected exception during session setup: ") << e.what() << endmsg; return -2; diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index 23f4714423..0e06917c8d 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -47,9 +47,9 @@ using namespace PBD; /* BBT TIME*/ void -Session::bbt_time (samplepos_t when, Temporal::BBT_Time& bbt) +Session::bbt_time (timepos_t const & when, Temporal::BBT_Time& bbt) { - bbt = _tempo_map->bbt_at_sample (when); + bbt = _tempo_map->bbt_at (when); } /* Timecode TIME */ @@ -241,7 +241,7 @@ Session::convert_to_samples (AnyTime const & position) switch (position.type) { case AnyTime::BBT: - return _tempo_map->sample_at_bbt (position.bbt); + return Temporal::superclock_to_samples (_tempo_map->superclock_at (position.bbt), _current_sample_rate); break; case AnyTime::Timecode: @@ -272,11 +272,12 @@ Session::convert_to_samples (AnyTime const & position) ARDOUR::samplecnt_t Session::any_duration_to_samples (samplepos_t position, AnyTime const & duration) { +#warning NUTEMPO THIS NEEDS A COMPLETE REVISION TO USE IMPLICIT CONVERSIONS ETC. double secs; switch (duration.type) { case AnyTime::BBT: - return (samplecnt_t) ( _tempo_map->samplepos_plus_bbt (position, duration.bbt) - position); + return Temporal::superclock_to_samples (_tempo_map->superclock_plus_bbt (Temporal::samples_to_superclock (position, _current_sample_rate), duration.bbt), _current_sample_rate) - position; break; case AnyTime::Timecode: diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 59f59fa04d..9f14614d26 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -69,7 +69,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; - +using namespace Temporal; #ifdef NDEBUG # define ENSURE_PROCESS_THREAD do {} while (0) @@ -527,15 +527,14 @@ Session::start_transport (bool after_loop) * - use [fixed] tempo/meter at _transport_sample * - calc duration of 1 bar + time-to-beat before or at transport_sample */ - const Tempo& tempo = _tempo_map->tempo_at_sample (_transport_sample); - const Meter& meter = _tempo_map->meter_at_sample (_transport_sample); + TempoMetric const & tempometric = _tempo_map->metric_at (_transport_sample); - const double num = meter.divisions_per_bar (); - const double den = meter.note_divisor (); - const double barbeat = _tempo_map->exact_qn_at_sample (_transport_sample, 0) * den / (4. * num); - const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed. + const double num = tempometric.divisions_per_bar (); + /* XXX possible optimization: get meter and BBT time in one call */ + const Temporal::BBT_Time bbt = _tempo_map->bbt_at (_transport_sample); + const double bar_fract = (double) bbt.beats / tempometric.divisions_per_bar(); - _count_in_samples = meter.samples_per_bar (tempo, _current_sample_rate); + _count_in_samples = tempometric.samples_per_bar (_current_sample_rate); double dt = _count_in_samples / num; if (bar_fract == 0) { diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc index d300b977d3..eb789670eb 100644 --- a/libs/ardour/session_vst.cc +++ b/libs/ardour/session_vst.cc @@ -42,6 +42,7 @@ #include "pbd/i18n.h" using namespace ARDOUR; +using namespace Temporal; #define SHOW_CALLBACK(MSG) DEBUG_TRACE (PBD::DEBUG::VSTCallbacks, string_compose (MSG " val = %1 idx = %2\n", index, value)) @@ -187,27 +188,27 @@ intptr_t Session::vst_callback ( timeinfo->sampleRate = session->sample_rate(); if (value & (kVstTempoValid)) { - const Tempo& t (session->tempo_map().tempo_at_sample (now)); + const Tempo& t (session->tempo_map().metric_at (now).tempo()); timeinfo->tempo = t.quarter_notes_per_minute (); newflags |= (kVstTempoValid); } if (value & (kVstTimeSigValid)) { - const MeterSection& ms (session->tempo_map().meter_section_at_sample (now)); + const Meter& ms (session->tempo_map().metric_at (now).meter()); timeinfo->timeSigNumerator = ms.divisions_per_bar (); - timeinfo->timeSigDenominator = ms.note_divisor (); + timeinfo->timeSigDenominator = ms.note_value (); newflags |= (kVstTimeSigValid); } if ((value & (kVstPpqPosValid)) || (value & (kVstBarsValid))) { Temporal::BBT_Time bbt; try { - bbt = session->tempo_map().bbt_at_sample_rt (now); + bbt = session->tempo_map().bbt_at (now); bbt.beats = 1; bbt.ticks = 0; /* exact quarter note */ - double ppqBar = session->tempo_map().quarter_note_at_bbt_rt (bbt); + double ppqBar = session->tempo_map().quarter_note_at (bbt); /* quarter note at sample position (not rounded to note subdivision) */ - double ppqPos = session->tempo_map().quarter_note_at_sample_rt (now); + double ppqPos = session->tempo_map().quarter_note_at (now); if (value & (kVstPpqPosValid)) { timeinfo->ppqPos = ppqPos; newflags |= kVstPpqPosValid; @@ -313,7 +314,7 @@ intptr_t Session::vst_callback ( SHOW_CALLBACK ("audioMasterTempoAt"); // returns tempo (in bpm * 10000) at sample sample location passed in if (session) { - const Tempo& t (session->tempo_map().tempo_at_sample (value)); + const Tempo& t (session->tempo_map().metric_at (value).tempo()); return t.quarter_notes_per_minute() * 1000; } else { return 0; diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc index 76458039c6..31619e2960 100644 --- a/libs/ardour/ticker.cc +++ b/libs/ardour/ticker.cc @@ -38,6 +38,7 @@ using namespace ARDOUR; using namespace PBD; +using namespace Temporal; MidiClockTicker::MidiClockTicker (Session* s) { @@ -166,7 +167,8 @@ MidiClockTicker::tick (samplepos_t start_sample, samplepos_t end_sample, pframes uint32_t beat_pos; samplepos_t clk_pos; - _session->tempo_map ().midi_clock_beat_at_of_after (start_sample + _mclk_out_latency.max, clk_pos, beat_pos); +#warning NUTEMPO need to reimplement this in TempoMap + // _session->tempo_map ().midi_clock_beat_at_of_after (start_sample + _mclk_out_latency.max, clk_pos, beat_pos); _beat_pos = beat_pos; _next_tick = clk_pos - _mclk_out_latency.max; @@ -213,8 +215,8 @@ out: double MidiClockTicker::one_ppqn_in_samples (samplepos_t transport_position) const { - const double samples_per_quarter_note = _session->tempo_map ().samples_per_quarter_note_at (transport_position, _session->nominal_sample_rate ()); - + Tempo const & tempo (_session->tempo_map().metric_at (transport_position).tempo()); + const double samples_per_quarter_note = tempo.samples_per_quarter_note (_session->nominal_sample_rate()); return samples_per_quarter_note / 24.0; } diff --git a/libs/ardour/wscript b/libs/ardour/wscript index e18c768d3e..3c76f9067b 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -441,7 +441,8 @@ def build(bld): #obj.add_objects = 'default/libs/surfaces/control_protocol/smpte_1.o' if bld.is_defined('HAVE_LILV') : - obj.source += ['lv2_plugin.cc', 'lv2_evbuf.c', 'uri_map.cc'] + # obj.source += ['lv2_plugin.cc', 'lv2_evbuf.c', 'uri_map.cc'] + obj.source += ['lv2_evbuf.c', 'uri_map.cc'] obj.uselib += ['LILV'] if bld.is_defined('HAVE_SUIL'): obj.uselib += ['SUIL'] diff --git a/libs/backends/jack/jack_session.cc b/libs/backends/jack/jack_session.cc index d94ce897a5..c96594bbd0 100644 --- a/libs/backends/jack/jack_session.cc +++ b/libs/backends/jack/jack_session.cc @@ -34,6 +34,7 @@ #include "jack_session.h" using namespace ARDOUR; +using namespace Temporal; using std::string; JACKSession::JACKSession (Session* s) @@ -128,14 +129,14 @@ JACKSession::timebase_callback (jack_transport_state_t /*state*/, TempoMetric metric (tempo_map.metric_at (tf)); try { - bbt = tempo_map.bbt_at_sample_rt (tf); + bbt = tempo_map.bbt_at (tf); pos->bar = bbt.bars; pos->beat = bbt.beats; pos->tick = bbt.ticks; pos->beats_per_bar = metric.meter().divisions_per_bar(); - pos->beat_type = metric.meter().note_divisor(); + pos->beat_type = metric.meter().note_value(); pos->ticks_per_beat = Temporal::ticks_per_beat; pos->beats_per_minute = metric.tempo().note_types_per_minute(); diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc index 9af0fc71e5..7fb1b83f8f 100644 --- a/libs/surfaces/control_protocol/basic_ui.cc +++ b/libs/surfaces/control_protocol/basic_ui.cc @@ -26,6 +26,8 @@ #include "pbd/pthread_utils.h" #include "pbd/memento_command.h" +#include "temporal/tempo.h" + #include "ardour/session.h" #include "ardour/location.h" #include "ardour/tempo.h" @@ -37,6 +39,7 @@ #include "pbd/i18n.h" using namespace ARDOUR; +using namespace Temporal; PBD::Signal2 BasicUI::AccessAction; @@ -543,10 +546,10 @@ BasicUI::jump_by_seconds (double secs, LocateTransportDisposition ltd) } void -BasicUI::jump_by_bars (double bars, LocateTransportDisposition ltd) +BasicUI::jump_by_bars (int bars, LocateTransportDisposition ltd) { TempoMap& tmap (session->tempo_map()); - Temporal::BBT_Time bbt (tmap.bbt_at_sample (session->transport_sample())); + Temporal::BBT_Time bbt (tmap.bbt_at (session->transport_sample())); bars += bbt.bars; if (bars < 0) { @@ -561,14 +564,14 @@ BasicUI::jump_by_bars (double bars, LocateTransportDisposition ltd) } void -BasicUI::jump_by_beats (double beats, LocateTransportDisposition ltd) +BasicUI::jump_by_beats (int beats, LocateTransportDisposition ltd) { - TempoMap& tmap (session->tempo_map ()); - double qn_goal = tmap.quarter_note_at_sample (session->transport_sample ()) + beats; - if (qn_goal < 0.0) { - qn_goal = 0.0; + Beats qn_goal = timepos_t (session->transport_sample ()).beats() + Beats (beats, 0); + + if (qn_goal < Beats()) { + qn_goal = Beats(); } - session->request_locate (tmap.sample_at_quarter_note (qn_goal), ltd); + session->request_locate (timepos_t (qn_goal).samples()); } void diff --git a/libs/surfaces/control_protocol/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h index 26d482b1f7..07f9cd84d9 100644 --- a/libs/surfaces/control_protocol/control_protocol/basic_ui.h +++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h @@ -76,8 +76,8 @@ class LIBCONTROLCP_API BasicUI { double transport_rolling () const; void jump_by_seconds (double sec, ARDOUR::LocateTransportDisposition ltd = ARDOUR::RollIfAppropriate); - void jump_by_bars (double bars, ARDOUR::LocateTransportDisposition ltd = ARDOUR::RollIfAppropriate); - void jump_by_beats (double beats, ARDOUR::LocateTransportDisposition ltd = ARDOUR::RollIfAppropriate); + void jump_by_bars (int bars, ARDOUR::LocateTransportDisposition ltd = ARDOUR::RollIfAppropriate); + void jump_by_beats (int beats, ARDOUR::LocateTransportDisposition ltd = ARDOUR::RollIfAppropriate); ARDOUR::samplepos_t transport_sample (); void locate (ARDOUR::samplepos_t sample, ARDOUR::LocateTransportDisposition ltd); diff --git a/libs/surfaces/faderport8/faderport8.cc b/libs/surfaces/faderport8/faderport8.cc index 1b48795ae9..3e2494620a 100644 --- a/libs/surfaces/faderport8/faderport8.cc +++ b/libs/surfaces/faderport8/faderport8.cc @@ -268,7 +268,7 @@ FaderPort8::periodic () _timecode = Timecode::timecode_format_time(TC); char buf[16]; - Temporal::BBT_Time BBT = session->tempo_map ().bbt_at_sample (session->transport_sample ()); + Temporal::BBT_Time BBT = session->tempo_map ().bbt_at (session->transport_sample ()); snprintf (buf, sizeof (buf), " %02" PRIu32 "|%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, BBT.bars % 100, BBT.beats %100, diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 96e6f7e600..1789ce5e02 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -1155,7 +1155,7 @@ MackieControlProtocol::format_bbt_timecode (samplepos_t now_sample) { Temporal::BBT_Time bbt_time; - session->bbt_time (now_sample, bbt_time); + session->bbt_time (timepos_t (now_sample), bbt_time); // The Mackie protocol spec is built around a BBT time display of // diff --git a/libs/surfaces/osc/osc_global_observer.cc b/libs/surfaces/osc/osc_global_observer.cc index b7ade2632e..492162fee8 100644 --- a/libs/surfaces/osc/osc_global_observer.cc +++ b/libs/surfaces/osc/osc_global_observer.cc @@ -244,7 +244,7 @@ OSCGlobalObserver::tick () if (feedback[5]) { // Bar beat enabled Temporal::BBT_Time bbt_time; - session->bbt_time (now_sample, bbt_time); + session->bbt_time (timepos_t (now_sample), bbt_time); // semantics: BBB/bb/tttt ostringstream os; diff --git a/libs/surfaces/push2/track_mix.cc b/libs/surfaces/push2/track_mix.cc index 34f95c0a4d..6e2f9544c3 100644 --- a/libs/surfaces/push2/track_mix.cc +++ b/libs/surfaces/push2/track_mix.cc @@ -603,7 +603,7 @@ TrackMixLayout::update_clocks () } char buf[16]; - Temporal::BBT_Time BBT = session.tempo_map().bbt_at_sample (pos); + Temporal::BBT_Time BBT = session.tempo_map().bbt_at (pos); #define BBT_BAR_CHAR "|" diff --git a/libs/surfaces/websockets/transport.cc b/libs/surfaces/websockets/transport.cc index a32188da1d..3716ffc064 100644 --- a/libs/surfaces/websockets/transport.cc +++ b/libs/surfaces/websockets/transport.cc @@ -22,12 +22,13 @@ using namespace ARDOUR; using namespace ArdourSurface; +using namespace Temporal; double ArdourTransport::tempo () const { - Tempo tempo = session ().tempo_map ().tempo_at_sample (0); - return tempo.note_type () * tempo.pulses_per_minute (); + const Tempo& tempo (session ().tempo_map ().metric_at (0).tempo()); + return tempo.note_types_per_minute (); } void @@ -35,8 +36,9 @@ ArdourTransport::set_tempo (double bpm) { bpm = std::max (0.01, bpm); TempoMap& tempo_map = session ().tempo_map (); - Tempo tempo (bpm, tempo_map.tempo_at_sample (0).note_type (), bpm); - tempo_map.add_tempo (tempo, 0.0, 0, AudioTime); + Tempo tempo (bpm, tempo_map.metric_at (0).tempo().note_type ()); +#warning NUTEMPO need some API to do this + // tempo_map.add_tempo (tempo, 0.0, 0, AudioTime); } double diff --git a/libs/temporal/tempo.cc b/libs/temporal/tempo.cc index 6141a4580a..99cf3a4df5 100644 --- a/libs/temporal/tempo.cc +++ b/libs/temporal/tempo.cc @@ -1683,7 +1683,7 @@ TempoMap::get_grid (TempoMapPoints& ret, superclock_t start, superclock_t end, u assert (!_tempos.empty()); assert (!_meters.empty()); - DEBUG_TRACE (DEBUG::TemporalMap, string_compose (">>> GRID START %1 .. %2 (barmod = %3)\n", start, end, bar_mod)); + DEBUG_TRACE (DEBUG::TemporalMap, string_compose (">>> GRID START %1 .. %2 (barmod = %3)\n", start, end, bar_mod)) Tempos::iterator t (_tempos.begin()); Meters::iterator m (_meters.begin()); diff --git a/libs/temporal/temporal/beats.h b/libs/temporal/temporal/beats.h index 8098816b24..7c98ceeeaf 100644 --- a/libs/temporal/temporal/beats.h +++ b/libs/temporal/temporal/beats.h @@ -40,7 +40,6 @@ namespace ARDOUR { class Variant; /* Can stay since LV2 has no way to exchange beats as anything except double */ /* these all need fixing to not use ::to_double() */ -class TempoMap; class Track; class MidiStretch; class MidiModel; @@ -440,7 +439,6 @@ private: /* almost nobody should ever be allowed to use this method */ friend class TempoPoint; - friend class ARDOUR::TempoMap; friend class ARDOUR::Track; friend class ARDOUR::Variant; friend class ARDOUR::MidiStretch; diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index daf3294d93..40aa3f5297 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -472,6 +472,10 @@ class LIBTEMPORAL_API TempoMetric { BBT_Time bbt_at (superclock_t sc) const; superclock_t superclock_at (BBT_Time const &) const; + samplepos_t samples_per_bar (samplecnt_t sr) const { + return superclock_to_samples (superclocks_per_bar (sr), sr); + } + protected: TempoPoint* _tempo; MeterPoint* _meter; @@ -723,7 +727,7 @@ class LIBTEMPORAL_API TempoMap : public PBD::StatefulDestructible TimeDomain time_domain() const { return _time_domain; } void set_time_domain (TimeDomain td); - void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end, uint32_t bar_mod); + void get_grid (TempoMapPoints& points, superclock_t start, superclock_t end, uint32_t bar_mod = 0); typedef std::list Metrics;