From 97f323137cd7ee538f435c62f87262e64fa1111f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 7 Oct 2021 08:03:46 -0600 Subject: [PATCH] triggerbox: initial (incorrect) attempt at handling tempo map changes --- gtk2_ardour/trigger_ui.cc | 2 +- libs/ardour/ardour/triggerbox.h | 8 +++++ libs/ardour/triggerbox.cc | 55 +++++++++++++++++++++++++-------- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/gtk2_ardour/trigger_ui.cc b/gtk2_ardour/trigger_ui.cc index 1c5f1cea5e..87d56c1712 100644 --- a/gtk2_ardour/trigger_ui.cc +++ b/gtk2_ardour/trigger_ui.cc @@ -104,7 +104,7 @@ TriggerUI::TriggerUI (Item* parent, Trigger& t) _follow_action_button = new ArdourButton (); _follow_action_button->set_text (_("Follow Action")); _follow_action_button->set_active_color (UIConfiguration::instance().color ("alert:greenish")); - + follow_action_button = new ArdourCanvas::Widget (canvas(), *_follow_action_button); follow_action_button->name = "FollowAction"; _follow_action_button->signal_event().connect (sigc::mem_fun (*this, (&TriggerUI::follow_action_button_event))); diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 3b527412db..16f4795202 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -78,6 +78,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful { virtual void set_end (timepos_t const &) = 0; /* this accepts timepos_t because the origin is assumed to be the start */ virtual void set_length (timecnt_t const &) = 0; + virtual void tempo_map_change () = 0; virtual double position_as_fraction() const = 0; @@ -192,6 +193,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful { PBD::Property _legato; std::string _name; double _stretch; + double _barcnt; /* our estimate of the number of bars in the region */ void* _ui; void set_region_internal (boost::shared_ptr); @@ -228,6 +230,8 @@ class LIBARDOUR_API AudioTrigger : public Trigger { XMLNode& get_state (void); int set_state (const XMLNode&, int version); + void tempo_map_change (); + protected: void retrigger (); void set_usable_length (); @@ -245,6 +249,7 @@ class LIBARDOUR_API AudioTrigger : public Trigger { void drop_data (); int load_data (boost::shared_ptr); RunResult at_end (); + void compute_and_set_length (); }; class LIBARDOUR_API TriggerBox : public Processor @@ -311,6 +316,9 @@ class LIBARDOUR_API TriggerBox : public Processor int determine_next_trigger (uint64_t n); void stop_all (); + void tempo_map_change (); + PBD::ScopedConnection tempo_map_connection; + void note_on (int note_number, int velocity); void note_off (int note_number, int velocity); diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 3a68b4fb22..d162e04fd5 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -61,6 +61,7 @@ Trigger::Trigger (uint64_t n, TriggerBox& b) , _quantization (Temporal::BBT_Offset (0, 1, 0)) , _legato (Properties::legato, true) , _stretch (1.0) + , _barcnt (0.) , _ui (0) { add_property (_legato); @@ -694,8 +695,6 @@ AudioTrigger::natural_length() const int AudioTrigger::set_region (boost::shared_ptr r) { - using namespace Temporal; - boost::shared_ptr ar = boost::dynamic_pointer_cast (r); if (!ar) { @@ -703,10 +702,18 @@ AudioTrigger::set_region (boost::shared_ptr r) } set_region_internal (r); - - /* load raw data */ - load_data (ar); + compute_and_set_length (); + + PropertyChanged (ARDOUR::Properties::name); + + return 0; +} + +void +AudioTrigger::compute_and_set_length () +{ + using namespace Temporal; /* now potentially stretch it to match our tempo. * @@ -715,29 +722,40 @@ AudioTrigger::set_region (boost::shared_ptr r) */ TempoMap::SharedPtr tm (TempoMap::use()); - TempoMetric const & metric (tm->metric_at (timepos_t (AudioTime))); - double barcnt; + if (_barcnt == 0) { - { + TempoMetric const & metric (tm->metric_at (timepos_t (AudioTime))); breakfastquay::MiniBPM mbpm (_box.session().sample_rate()); mbpm.setBPMRange (metric.tempo().quarter_notes_per_minute () * 0.75, metric.tempo().quarter_notes_per_minute() * 1.5); double bpm = mbpm.estimateTempoOfSamples (data[0], data_length); + const double seconds = (double) data_length / _box.session().sample_rate(); const double quarters = (seconds / 60.) * bpm; - barcnt = quarters / metric.meter().divisions_per_bar(); + _barcnt = quarters / metric.meter().divisions_per_bar(); } /* use initial tempo in map (assumed for now to be the only one */ - samplecnt_t one_bar = tm->bbt_duration_at (timepos_t (AudioTime), BBT_Offset (1, 0, 0)).samples(); + const samplecnt_t one_bar = tm->bbt_duration_at (timepos_t (AudioTime), BBT_Offset (1, 0, 0)).samples(); - set_length (timecnt_t ((samplecnt_t) round (barcnt) * one_bar)); + cerr << "one bar in samples: " << one_bar << endl; + cerr << "barcnt = " << round (_barcnt) << endl; - PropertyChanged (ARDOUR::Properties::name); + set_length (timecnt_t ((samplecnt_t) round (_barcnt) * one_bar)); +} - return 0; +void +AudioTrigger::tempo_map_change () +{ + if (!_region) { + return; + } + + drop_data (); + load_data (boost::dynamic_pointer_cast (_region)); + compute_and_set_length (); } void @@ -914,6 +932,8 @@ TriggerBox::TriggerBox (Session& s, DataType dt) midi_trigger_map.insert (midi_trigger_map.end(), std::make_pair (uint8_t (67), 7)); midi_trigger_map.insert (midi_trigger_map.end(), std::make_pair (uint8_t (68), 8)); midi_trigger_map.insert (midi_trigger_map.end(), std::make_pair (uint8_t (69), 9)); + + Temporal::TempoMap::MapChanged.connect_same_thread (tempo_map_connection, boost::bind (&TriggerBox::tempo_map_change, this)); } void @@ -1566,3 +1586,12 @@ TriggerBox::set_state (const XMLNode& node, int version) return 0; } + +void +TriggerBox::tempo_map_change () +{ + Glib::Threads::RWLock::ReaderLock lm (trigger_lock); + for (auto & t : all_triggers) { + t->tempo_map_change (); + } +}