diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 12c107b927..f3d2379e3c 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -101,6 +101,14 @@ class LIBARDOUR_API Trigger : public PBD::Stateful { XMLNode& get_state (void); int set_state (const XMLNode&, int version); + enum RunResult { + Relax = 0, + RemoveTrigger = 0x1, + ReadMore = 0x2, + FillSilence = 0x4, + ChangeTriggers = 0x8 + }; + protected: TriggerBox& _box; bool _running; @@ -122,7 +130,7 @@ class LIBARDOUR_API AudioTrigger : public Trigger { void bang (TriggerBox&); void unbang (TriggerBox&, Temporal::Beats const & , samplepos_t); - int run (AudioBuffer&, uint32_t channel, pframes_t nframes, pframes_t offset, bool first); + RunResult run (AudioBuffer&, uint32_t channel, pframes_t& nframes, pframes_t offset, bool first); void set_length (timecnt_t const &); timecnt_t current_length() const; @@ -138,6 +146,7 @@ class LIBARDOUR_API AudioTrigger : public Trigger { void drop_data (); int load_data (boost::shared_ptr); + RunResult at_end (); }; class LIBARDOUR_API TriggerBox : public Processor diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 0fe535b89c..ca91820038 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -346,6 +346,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp } size_t max_chans = 0; + Trigger::RunResult rr; for (Triggers::iterator t = active_triggers.begin(); t != active_triggers.end(); ) { @@ -376,33 +377,57 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp } AudioTrigger* at = dynamic_cast (trigger); - bool err = false; if (at) { boost::shared_ptr ar = boost::dynamic_pointer_cast (r); const bool first = (t == active_triggers.begin()); const size_t nchans = ar->n_channels (); + pframes_t nf = trigger_samples; max_chans = std::max (max_chans, nchans); + read_more: for (uint32_t chan = 0; chan < nchans; ++chan) { - if (at->run (bufs.get_audio (chan), chan, trigger_samples, dest_offset, first)) { - err = true; - break; + /* we assume the result will be the same for all channels */ + + AudioBuffer& buf (bufs.get_audio (chan)); + + rr = at->run (buf, chan, nf, dest_offset, first); + + /* nf is now the number of samples that were + * actually processed/generated/written + */ + + if (rr & Trigger::FillSilence) { + buf.silence (trigger_samples - nf, nf + dest_offset); } } + + if (rr == Trigger::ReadMore) { + trigger_samples -= nf; + goto read_more; + } + } else { - /* XXX to be written */ + /* XXX MIDI triggers to be implemented */ } - if (err) { + if (rr & Trigger::RemoveTrigger) { t = active_triggers.erase (t); - } else { - ++t; + continue; } + + ++t; + + if (rr & Trigger::ChangeTriggers) { + /* XXX do this! */ + std::cerr << "Should change triggers!\n"; + } + + } ChanCount cc (DataType::AUDIO, max_chans); @@ -560,7 +585,7 @@ AudioTrigger::set_length (timecnt_t const & newlen) /* study, then process */ - const samplecnt_t block_size = 8192; + const samplecnt_t block_size = 16384; samplecnt_t read = 0; stretcher.setDebugLevel (0); @@ -754,58 +779,80 @@ AudioTrigger::unbang (TriggerBox& /*proc*/, Temporal::Beats const &, samplepos_t } } -int -AudioTrigger::run (AudioBuffer& buf, uint32_t channel, pframes_t nframes, pframes_t dest_offset, bool first) +Trigger::RunResult +AudioTrigger::run (AudioBuffer& buf, uint32_t channel, pframes_t& nframes, pframes_t dest_offset, bool first) { if (!_running) { - return -1; + return RemoveTrigger; } if (read_index[channel] >= data_length) { _running = false; - return -1; + return RemoveTrigger; } if (_stop_requested) { - /* XXX need fade out machinery */ + /* XXX need fade out machinery instead of immediate stop */ _running = false; _stop_requested = false; - return 0; + return RemoveTrigger; } channel %= data.size(); - read_more: pframes_t nf = (pframes_t) std::min ((samplecnt_t) nframes, (data_length - read_index[channel])); Sample* src = data[channel] + read_index[channel]; if (first) { buf.read_from (src, nf, dest_offset); - if ((nf + dest_offset) < nframes) { - buf.silence (nframes - nf, nf + dest_offset); - } } else { buf.accumulate_from (src, nf); } read_index[channel] += nf; - if (nf < nframes) { + nframes -= nf; - nframes -= nf; - - switch (launch_style()) { - case Trigger::Loop: - retrigger(); - goto read_more; - break; - case Trigger::Gate: - case Trigger::Toggle: - case Trigger::Repeat: - return -1; - break; - } + if (nframes != 0) { + /* did not get all samples, must have reached the end, figure out what do to */ + return at_end (); } - return 0; + return Relax; +} + +Trigger::RunResult +AudioTrigger::at_end () +{ + switch (launch_style()) { + case Trigger::Loop: + retrigger(); + return ReadMore; /* means keep reading */ + + case Trigger::Gate: + case Trigger::Toggle: + case Trigger::Repeat: + break; + } + + switch (follow_action()) { + case Stop: + return RunResult (RemoveTrigger|FillSilence); + case QueuedTrigger: + break; + case NextTrigger: + break; + case PrevTrigger: + break; + case FirstTrigger: + break; + case LastTrigger: + break; + case AnyTrigger: + break; + case OtherTrigger: + break; + } + + return ChangeTriggers; }