From 66fe6e937acab66cdf3b7492ad877d3414f46786 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 26 Oct 2021 17:34:06 -0600 Subject: [PATCH] triggerbox: vaguely working MIDI triggers --- libs/ardour/ardour/triggerbox.h | 4 +-- libs/ardour/triggerbox.cc | 52 +++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 0095ad031d..7c6951b3b5 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -201,7 +201,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful { PBD::Property _use_follow; FollowAction _follow_action[2]; int _follow_action_probability; - uint32_t _follow_cnt; + uint32_t _loop_cnt; uint32_t _follow_count; boost::shared_ptr _region; Temporal::BBT_Offset _quantization; @@ -274,7 +274,7 @@ class LIBARDOUR_API MIDITrigger : public Trigger { MIDITrigger (uint64_t index, TriggerBox&); ~MIDITrigger (); - int run (BufferSet&, pframes_t nframes, pframes_t offset, bool first); + int run (BufferSet&, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, pframes_t offset, bool first); void set_start (timepos_t const &); void set_end (timepos_t const &); diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 1fcdc139d4..78d5057315 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -59,7 +59,7 @@ Trigger::Trigger (uint64_t n, TriggerBox& b) , _use_follow (Properties::use_follow, true) , _follow_action { NextTrigger, Stop } , _follow_action_probability (100) - , _follow_cnt (0) + , _loop_cnt (0) , _follow_count (1) , _quantization (Temporal::BBT_Offset (0, 1, 0)) , _legato (Properties::legato, false) @@ -256,7 +256,8 @@ Trigger::startup() { _state = WaitingToStart; _gain = _pending_gain; - _follow_cnt = _follow_count; + _loop_cnt = 0; + DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 starts up\n", name())); PropertyChanged (ARDOUR::Properties::running); } @@ -265,6 +266,7 @@ Trigger::shutdown () { _state = Stopped; _gain = 1.0; + DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 shuts down\n", name())); PropertyChanged (ARDOUR::Properties::running); } @@ -429,6 +431,8 @@ Trigger::maybe_compute_next_transition (Temporal::Beats const & start, Temporal: transition_samples = transition_time.samples(); transition_beats = transition_time.beats (); + DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 in range, should start/stop at %2 aka %3\n", index(), transition_samples, transition_beats)); + if (_state == WaitingToStop) { _state = Stopping; PropertyChanged (ARDOUR::Properties::running); @@ -820,6 +824,7 @@ AudioTrigger::drop_data () } int + AudioTrigger::load_data (boost::shared_ptr ar) { const uint32_t nchans = ar->n_channels(); @@ -903,9 +908,9 @@ AudioTrigger::run (BufferSet& bufs, pframes_t nframes, pframes_t dest_offset, bo /* We reached the end */ - _follow_cnt--; + _loop_cnt++; - if ((_follow_cnt != 0) || (_launch_style == Repeat) || (_box.peek_next_trigger() == this)) { /* self repeat */ + if ((_loop_cnt == _follow_count) || (_launch_style == Repeat) || (_box.peek_next_trigger() == this)) { /* self repeat */ nframes -= this_read; dest_offset += this_read; DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, but set to loop, so retrigger\n", index())); @@ -1176,8 +1181,10 @@ int MIDITrigger::load_data (boost::shared_ptr mr) { drop_data (); - mr->render (data, 0, Sustained, 0); + mr->render_range (data, 0, Sustained, mr->start(), mr->length(), timepos_t (Temporal::BeatTime), 0); + set_name (mr->name()); data_length = data.span(); + DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 loaded midi region, span is %2\n", name(), data_length)); return 0; } @@ -1189,30 +1196,34 @@ MIDITrigger::retrigger () read_index = 0; end_run_sample = transition_samples; _legato_offset = Temporal::BBT_Offset (); - DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 retriggered to %2\n", _index, read_index)); + DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 retriggered to %2, ts = %3\n", _index, read_index, transition_samples)); } int -MIDITrigger::run (BufferSet& bufs, pframes_t nframes, pframes_t dest_offset, bool first) +MIDITrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, pframes_t dest_offset, bool first) { MidiBuffer& mb (bufs.get_midi (0)); - end_run_sample += nframes; - while (true) { RTMidiBuffer::Item const & item (data[read_index]); /* timestamps inside the RTMidiBuffer are relative to zero. Offset them to give us process/timeline timestamps. */ - const samplepos_t effective_time = transition_samples + item.timestamp; - if (effective_time < end_run_sample) { + const samplepos_t effective_time = transition_samples + item.timestamp + (_loop_cnt * data_length); /* XXX handle multiple loops */ + + // cerr << "Item " << read_index << " @ " << item.timestamp << " + " << transition_samples << " = " << effective_time << endl; + + if (effective_time < end_sample) { uint32_t sz; uint8_t const * bytes = data.bytes (item, sz); - const Evoral::Event ev (Evoral::MIDI_EVENT, item.timestamp, sz, const_cast(bytes), false); + samplepos_t process_relative_timestamp = effective_time - start_sample; + + const Evoral::Event ev (Evoral::MIDI_EVENT, process_relative_timestamp, sz, const_cast(bytes), false); + DEBUG_TRACE (DEBUG::Triggers, string_compose ("inserting %1\n", ev)); mb.insert_event (ev); // _tracker.track (bytes); @@ -1220,14 +1231,18 @@ MIDITrigger::run (BufferSet& bufs, pframes_t nframes, pframes_t dest_offset, boo read_index++; } else { + break; + } + + if (read_index >= data.size()) { /* We reached the end */ // _tracker.resolve_notes (mb); - _follow_cnt--; + _loop_cnt++; - if ((_follow_cnt != 0) || (_launch_style == Repeat) || (_box.peek_next_trigger() == this)) { /* self repeat */ + if ((_loop_cnt == _follow_count) || (_launch_style == Repeat) || (_box.peek_next_trigger() == this)) { /* self repeat */ DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, but set to loop, so retrigger\n", index())); /* We need to preserve end_run_sample across @@ -1380,6 +1395,8 @@ TriggerBox::get_next_trigger () int TriggerBox::set_from_selection (uint64_t slot, boost::shared_ptr region) { + DEBUG_TRACE (DEBUG::Triggers, string_compose ("load %1 into %2\n", region->name(), slot)); + if (slot >= all_triggers.size()) { return 0; } @@ -1760,6 +1777,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp case Trigger::WaitingToStop: case Trigger::WaitingToStart: case Trigger::WaitingForRetrigger: + DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 in state %2, recompute next transition\n", currently_playing->name(), currently_playing->state())); rt = currently_playing->maybe_compute_next_transition (start_beats, end_beats); break; default: @@ -1829,8 +1847,12 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp first = false; } else { + MIDITrigger* mt = dynamic_cast (currently_playing); - /* XXX MIDI triggers to be implemented */ + if (mt) { + mt->run (bufs, start_sample, end_sample, trigger_samples, dest_offset, first); + first = false; + } }