From 2995b2a0bb67a7bd058740867ec96243733339e1 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sat, 17 Jul 2021 19:01:10 -0600 Subject: [PATCH] super-basic working MIDI triggering for TriggerBox --- libs/ardour/ardour/triggerbox.h | 10 +++- libs/ardour/triggerbox.cc | 97 ++++++++++++++++----------------- 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 719b93fbdd..de3eb2bed5 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -42,10 +42,14 @@ class TriggerBox; class LIBARDOUR_API Trigger { public: - Trigger() {} + Trigger() : _running (false) {} virtual ~Trigger() {} virtual void bang (TriggerBox&, Temporal::Beats const &, samplepos_t) = 0; + bool running() const { return _running; } + + protected: + bool _running; }; class LIBARDOUR_API AudioTrigger : public Trigger { @@ -58,9 +62,8 @@ class LIBARDOUR_API AudioTrigger : public Trigger { private: boost::shared_ptr region; - bool running; std::vector data; - samplecnt_t read_index; + std::vector read_index; samplecnt_t length; }; @@ -72,6 +75,7 @@ class LIBARDOUR_API TriggerBox : public Processor void run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required); bool can_support_io_configuration (const ChanCount& in, ChanCount& out); + bool configure_io (ChanCount in, ChanCount out); bool queue_trigger (Trigger*); void add_trigger (Trigger*); diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index f352e6d712..2286cf4cdf 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -19,7 +19,7 @@ TriggerBox::TriggerBox (Session& s) { PropertyList plist; - the_source.reset (new SndFileSource (_session, "/usr/share/sounds/alsa/Front_Center.wav", 0, Source::Flag (0))); + the_source.reset (new SndFileSource (_session, "/music/misc/La_Voz_Del_Rio.wav", 0, Source::Flag (0))); plist.add (Properties::start, 0); plist.add (Properties::length, the_source->length ()); @@ -30,8 +30,6 @@ TriggerBox::TriggerBox (Session& s) boost::shared_ptr r = RegionFactory::create (the_source, plist, false); the_region = boost::dynamic_pointer_cast (r); - cerr << "Trigger track has region " << the_region->name() << " length = " << the_region->length() << endl; - /* XXX the_region/trigger will be looked up in a std::map */ @@ -50,24 +48,16 @@ TriggerBox::can_support_io_configuration (const ChanCount& in, ChanCount& out) return false; } + out = ChanCount::max (out, ChanCount (DataType::AUDIO, 2)); + return true; } - -void -TriggerBox::note_on (int note_number, int velocity) -{ - if (velocity == 0) { - note_off (note_number, velocity); - return; - } - - queue_trigger (the_trigger); -} - -void -TriggerBox::note_off (int note_number, int velocity) +bool +TriggerBox::configure_io (ChanCount in, ChanCount out) { + cerr << "TB: " << in << " / " << out << endl; + return Processor::configure_io (in, out); } void @@ -87,6 +77,9 @@ TriggerBox::queue_trigger (Trigger* trigger) void TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required) { + samplepos_t next_beat = 0; + Temporal::Beats beats_now; + /* check MIDI port input buffers for triggers */ for (BufferSet::midi_iterator mi = bufs.midi_begin(); mi != bufs.midi_end(); ++mi) { @@ -94,8 +87,12 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp for (MidiBuffer::iterator ev = mb.begin(); ev != mb.end(); ++ev) { if ((*ev).is_note_on()) { - cerr << "Trigger => NOTE ON!\n"; - note_on ((*ev).note(), (*ev).velocity()); + + if (!the_trigger->running()) { + active_triggers.push_back (the_trigger); + } + + the_trigger->bang (*this, beats_now, start_sample); } } } @@ -105,9 +102,6 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp /* find offset to next bar * and beat start */ - samplepos_t next_beat = 0; - Temporal::Beats beats_now; - /* if next beat occurs in this process cycle, see if we have any triggers waiting */ @@ -118,7 +112,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp //run_beats = true; //} - /* if there are any triggers queued, run them. + /* if there are any triggers queued, make them active */ RingBuffer::rw_vector vec; @@ -128,25 +122,26 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp Trigger* t = vec.buf[0][n]; t->bang (*this, beats_now, start_sample); active_triggers.push_back (t); - cerr << "Trigger goes bang at " << start_sample << endl; } for (uint32_t n = 0; n < vec.len[1]; ++n) { Trigger* t = vec.buf[1][n]; t->bang (*this, beats_now, start_sample); active_triggers.push_back (t); - cerr << "Trigger goes bang at " << start_sample << endl; } _trigger_queue.increment_read_idx (vec.len[0] + vec.len[1]); bool err = false; - size_t chan = 0; - const size_t nchans = bufs.count().get (DataType::AUDIO); + const size_t nchans = the_region->n_channels (); bool need_butler = false; - for (Triggers::iterator t = active_triggers.begin(); !err && t != active_triggers.end(); ) { + for (uint32_t chan = 0; chan < nchans; ++chan) { + AudioBuffer& buf = bufs.get_audio (chan); + buf.silence (nframes, 0); + } + for (Triggers::iterator t = active_triggers.begin(); !err && t != active_triggers.end(); ++t) { AudioTrigger* at = dynamic_cast (*t); @@ -159,22 +154,30 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp AudioBuffer& buf = bufs.get_audio (chan); pframes_t to_copy = nframes; - Sample* data = at->run (chan, to_copy, start_sample, end_sample, need_butler); if (!data) { /* XXX need to delete the trigger/put it back in the pool */ + cerr << "trigger complete\n"; t = active_triggers.erase (t); err = true; } else { if (t == active_triggers.begin()) { buf.read_from (data, to_copy); + if (to_copy < nframes) { + buf.silence (nframes - to_copy, to_copy); + } } else { buf.accumulate_from (data, to_copy); } } + } } + + ChanCount cc (DataType::AUDIO, nchans); + cc.set_midi (bufs.count().n_midi()); + bufs.set_count (cc); } XMLNode& @@ -194,24 +197,20 @@ TriggerBox::set_state (const XMLNode&, int version) AudioTrigger::AudioTrigger (boost::shared_ptr r) : region (r) - , running (false) , data (0) - , read_index (0) , length (0) { /* XXX catch region going away */ const uint32_t nchans = region->n_channels(); - cerr << "Trigger needs " << nchans << " channels of " << region->length() << " each\n"; - length = region->length_samples(); for (uint32_t n = 0; n < nchans; ++n) { - data.push_back (new Sample (length));; - // region->read (data[n], 0, length, n); + data.push_back (new Sample[length]);; + read_index.push_back (0); + region->read (data[n], 0, length, n); } - } AudioTrigger::~AudioTrigger () @@ -228,30 +227,28 @@ AudioTrigger::bang (TriggerBox& /*proc*/, Temporal::Beats const &, samplepos_t) * run() */ - read_index = 0; - running = true; + for (std::vector::iterator ri = read_index.begin(); ri != read_index.end(); ++ri) { + (*ri) = 0; + } + + _running = true; } Sample* -AudioTrigger::run (uint32_t channel, pframes_t& nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler) +AudioTrigger::run (uint32_t channel, pframes_t& nframes, samplepos_t /*start_sample*/, samplepos_t /*end_sample*/, bool& /* need_butler */) { - if (!running) { + if (!_running) { return 0; } - if (read_index >= length) { + if (read_index[channel] >= length) { return 0; } - if (channel >= data.size()) { - return 0; - } + channel %= data.size(); - nframes = (pframes_t) std::min ((samplecnt_t) nframes, (length - read_index)); + nframes = (pframes_t) std::min ((samplecnt_t) nframes, (length - read_index[channel])); + read_index[channel] += nframes; - Sample* ret = data[channel] + read_index; - - read_index += nframes; - - return ret; + return data[channel] + read_index[channel]; }