From c09ffd4fcdbd8a471afb340d47da6cc95d448d1e Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 15 Feb 2022 16:24:01 -0700 Subject: [PATCH] triggerbox: consolidate ::start_and_roll_to() across Audio & MIDI triggers This uses a mild trick to pass both the object and ptr-to-member-function from the child class to the parent class. Note: before this commit, both instances of ::start_and_roll_to() were identical. --- libs/ardour/ardour/triggerbox.h | 6 ++ libs/ardour/triggerbox.cc | 126 +++++++++++++------------------- 2 files changed, 56 insertions(+), 76 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 18d9fbb16a..a713a74946 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -310,6 +310,12 @@ class LIBARDOUR_API Trigger : public PBD::Stateful { Temporal::BBT_Time& t_bbt, Temporal::Beats& t_beats, samplepos_t& t_samples, Temporal::TempoMap::SharedPtr const & tmap); + + template + void start_and_roll_to (samplepos_t start_pos, samplepos_t end_position, TriggerType& trigger, + pframes_t (TriggerType::*run_method) (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, + Temporal::Beats const & start_beats, Temporal::Beats const & end_beats, + pframes_t nframes, pframes_t dest_offset, double bpm)); void set_next_trigger (int n); int next_trigger() const { return _next_trigger; } diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 78099cbc0a..9c71363be2 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -1026,6 +1026,54 @@ Trigger::when_stopped_during_run (BufferSet& bufs, pframes_t dest_offset) } } +template +void +Trigger::start_and_roll_to (samplepos_t start_pos, samplepos_t end_position, TriggerType& trigger, + pframes_t (TriggerType::*run_method) (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, + Temporal::Beats const & start_beats, Temporal::Beats const & end_beats, + pframes_t nframes, pframes_t dest_offset, double bpm)) +{ + const pframes_t block_size = AudioEngine::instance()->samples_per_cycle (); + BufferSet bufs; + + /* no need to allocate any space for BufferSet because we call + audio_run() which is guaranteed to never use the buffers. + + AudioTrigger::_startup() also does not use BufferSet (MIDITrigger + does, and we use virtual functions so the argument list is the same + for both, even though only the MIDI case needs the BufferSet). + */ + + startup (bufs, 0, _quantization); + _cue_launched = true; + + samplepos_t pos = start_pos; + Temporal::TempoMap::SharedPtr tmap (Temporal::TempoMap::use()); + + while (pos < end_position) { + pframes_t nframes = std::min (block_size, (pframes_t) (end_position - pos)); + Temporal::Beats start_beats = tmap->quarters_at (timepos_t (pos)); + Temporal::Beats end_beats = tmap->quarters_at (timepos_t (pos+nframes)); + const double bpm = tmap->quarters_per_minute_at (timepos_t (start_beats)); + + pframes_t n = (trigger.*run_method) (bufs, pos, pos+nframes, start_beats, end_beats, nframes, 0, bpm); + + /* We could have reached the end. Check and restart, because + * TriggerBox::fast_forward() already determined that we are + * the active trigger at @param end_position + */ + + if (_state == Stopped) { + retrigger (); + _state = WaitingToStart; + _cue_launched = true; + } + + pos += n; + } +} + + /*--------------------*/ @@ -1189,44 +1237,7 @@ AudioTrigger::start_offset () const void AudioTrigger::start_and_roll_to (samplepos_t start_pos, samplepos_t end_position) { - const pframes_t block_size = AudioEngine::instance()->samples_per_cycle (); - BufferSet bufs; - - /* no need to allocate any space for BufferSet because we call - audio_run() which is guaranteed to never use the buffers. - - AudioTrigger::_startup() also does not use BufferSet (MIDITrigger - does, and we use virtual functions so the argument list is the same - for both, even though only the MIDI case needs the BufferSet). - */ - - startup (bufs, 0, _quantization); - _cue_launched = true; - - samplepos_t pos = start_pos; - Temporal::TempoMap::SharedPtr tmap (Temporal::TempoMap::use()); - - while (pos < end_position) { - pframes_t nframes = std::min (block_size, (pframes_t) (end_position - pos)); - Temporal::Beats start_beats = tmap->quarters_at (timepos_t (pos)); - Temporal::Beats end_beats = tmap->quarters_at (timepos_t (pos+nframes)); - const double bpm = tmap->quarters_per_minute_at (timepos_t (start_beats)); - - pframes_t n = audio_run (bufs, pos, pos+nframes, start_beats, end_beats, nframes, 0, bpm); - - /* We could have reached the end. Check and restart, because - * TriggerBox::fast_forward() already determined that we are - * the active trigger at @param end_position - */ - - if (_state == Stopped) { - retrigger (); - _state = WaitingToStart; - _cue_launched = true; - } - - pos += n; - } + Trigger::start_and_roll_to (start_pos, end_position, *this, &AudioTrigger::audio_run); } timepos_t @@ -2049,44 +2060,7 @@ MIDITrigger::probably_oneshot () const void MIDITrigger::start_and_roll_to (samplepos_t start_pos, samplepos_t end_position) { - const pframes_t block_size = AudioEngine::instance()->samples_per_cycle (); - BufferSet bufs; - - /* no need to allocate any space for BufferSet because we call - audio_run() which is guaranteed to never use the buffers. - - AudioTrigger::_startup() also does not use BufferSet (MIDITrigger - does, and we use virtual functions so the argument list is the same - for both, even though only the MIDI case needs the BufferSet). - */ - - startup (bufs, 0, _quantization); - _cue_launched = true; - - samplepos_t pos = start_pos; - Temporal::TempoMap::SharedPtr tmap (Temporal::TempoMap::use()); - - while (pos < end_position) { - pframes_t nframes = std::min (block_size, (pframes_t) (end_position - pos)); - Temporal::Beats start_beats = tmap->quarters_at (timepos_t (pos)); - Temporal::Beats end_beats = tmap->quarters_at (timepos_t (pos+nframes)); - const double bpm = tmap->quarters_per_minute_at (timepos_t (start_beats)); - - pframes_t n = midi_run (bufs, pos, pos+nframes, start_beats, end_beats, nframes, 0, bpm); - - /* We could have reached the end. Check and restart, because - * TriggerBox::fast_forward() already determined that we are - * the active trigger at @param end_position - */ - - if (_state == Stopped) { - retrigger (); - _state = WaitingToStart; - _cue_launched = true; - } - - pos += n; - } + Trigger::start_and_roll_to (start_pos, end_position, *this, &MIDITrigger::midi_run); } timepos_t