mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-08 22:55:44 +01:00
triggerbox: various improvements, including legato support, state tracking
This commit is contained in:
parent
3734277263
commit
584e5c5b45
2 changed files with 63 additions and 8 deletions
|
|
@ -69,6 +69,9 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
|||
|
||||
static void make_property_quarks ();
|
||||
|
||||
void set_name (std::string const &);
|
||||
std::string name() const { return _name; }
|
||||
|
||||
/* semantics of "bang" depend on the trigger */
|
||||
void bang ();
|
||||
void unbang ();
|
||||
|
|
@ -77,8 +80,8 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
|||
/* explicitly call for the trigger to start */
|
||||
virtual void start();
|
||||
|
||||
virtual void set_start (timepos_t) = 0;
|
||||
virtual void set_end (timepos_t) = 0;
|
||||
virtual void set_start (timepos_t const &) = 0;
|
||||
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 (timepos_t const &) = 0;
|
||||
|
||||
|
|
@ -156,6 +159,11 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
|||
void set_follow_action_probability (int zero_to_a_hundred);
|
||||
int follow_action_probability() const { return _follow_action_probability; }
|
||||
|
||||
virtual void set_legato_offset (timepos_t const & offset) = 0;
|
||||
virtual timepos_t current_pos() const = 0;
|
||||
void set_legato (bool yn);
|
||||
bool legato () const { return _legato; }
|
||||
|
||||
protected:
|
||||
TriggerBox& _box;
|
||||
State _state;
|
||||
|
|
@ -169,6 +177,8 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
|||
int _follow_action_probability;
|
||||
boost::shared_ptr<Region> _region;
|
||||
Temporal::BBT_Offset _quantization;
|
||||
bool _legato;
|
||||
std::string _name;
|
||||
|
||||
void set_region_internal (boost::shared_ptr<Region>);
|
||||
void request_state (State s);
|
||||
|
|
@ -183,8 +193,10 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
|
|||
|
||||
int run (BufferSet&, pframes_t nframes, pframes_t offset, bool first);
|
||||
|
||||
void set_start (timepos_t);
|
||||
void set_end (timepos_t);
|
||||
void set_start (timepos_t const &);
|
||||
void set_end (timepos_t const &);
|
||||
void set_legato_offset (timepos_t const &);
|
||||
timepos_t current_pos() const;
|
||||
/* this accepts timepos_t because the origin is assumed to be the start */
|
||||
void set_length (timepos_t const &);
|
||||
timepos_t start_offset () const { return timepos_t (_start_offset); } /* offset from start of data */
|
||||
|
|
@ -203,6 +215,7 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
|
|||
samplecnt_t read_index;
|
||||
samplecnt_t data_length;
|
||||
samplepos_t _start_offset;
|
||||
samplepos_t _legato_offset;
|
||||
samplecnt_t usable_length;
|
||||
samplepos_t last_sample;
|
||||
|
||||
|
|
@ -260,6 +273,8 @@ class LIBARDOUR_API TriggerBox : public Processor
|
|||
|
||||
typedef std::map<uint8_t,Triggers::size_type> MidiTriggerMap;
|
||||
MidiTriggerMap midi_trigger_map;
|
||||
|
||||
static const size_t default_triggers_per_box;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -45,9 +45,16 @@ Trigger::Trigger (size_t n, TriggerBox& b)
|
|||
, _follow_action { NextTrigger, Stop }
|
||||
, _follow_action_probability (100)
|
||||
, _quantization (Temporal::BBT_Offset (0, 1, 0))
|
||||
, _legato (false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Trigger::set_name (std::string const & str)
|
||||
{
|
||||
_name = str;
|
||||
}
|
||||
|
||||
void
|
||||
Trigger::bang ()
|
||||
{
|
||||
|
|
@ -150,10 +157,12 @@ Trigger::process_state_requests ()
|
|||
case Stopped:
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 %2 -> %3\n", index(), enum_2_string (_state), enum_2_string (WaitingToStop)));
|
||||
_state = WaitingToStop;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
break;
|
||||
case Running:
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 %2 -> %3\n", index(), enum_2_string (_state), enum_2_string (WaitingToStart)));
|
||||
_state = WaitingToStart;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -180,18 +189,21 @@ Trigger::process_state_requests ()
|
|||
case OneShot:
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 %2 -> %3\n", index(), enum_2_string (Running), enum_2_string (WaitingForRetrigger)));
|
||||
_state = WaitingForRetrigger;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
break;
|
||||
case Gate:
|
||||
case Toggle:
|
||||
case Repeat:
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 %2 -> %3\n", index(), enum_2_string (Running), enum_2_string (Stopped)));
|
||||
_state = WaitingToStop;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
}
|
||||
break;
|
||||
|
||||
case Stopped:
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 %2 -> %3\n", index(), enum_2_string (Stopped), enum_2_string (WaitingToStart)));
|
||||
_state = WaitingToStart;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
break;
|
||||
|
||||
case WaitingToStart:
|
||||
|
|
@ -211,11 +223,13 @@ Trigger::process_state_requests ()
|
|||
switch (_state) {
|
||||
case Running:
|
||||
_state = WaitingToStop;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 unbanged, now in WaitingToStop\n", index()));
|
||||
break;
|
||||
default:
|
||||
/* didn't even get started */
|
||||
_state = Stopped;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 unbanged, never started, now stopped\n", index()));
|
||||
}
|
||||
}
|
||||
|
|
@ -254,14 +268,17 @@ Trigger::maybe_compute_next_transition (Temporal::Beats const & start, Temporal:
|
|||
|
||||
if (_state == WaitingToStop) {
|
||||
_state = Stopping;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
return RunEnd;
|
||||
} else if (_state == WaitingToStart) {
|
||||
retrigger ();
|
||||
_state = Running;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
return RunStart;
|
||||
} else if (_state == WaitingForRetrigger) {
|
||||
retrigger ();
|
||||
_state = Running;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
return RunAll;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -292,6 +309,7 @@ AudioTrigger::AudioTrigger (size_t n, TriggerBox& b)
|
|||
, read_index (0)
|
||||
, data_length (0)
|
||||
, _start_offset (0)
|
||||
, _legato_offset (0)
|
||||
, usable_length (0)
|
||||
, last_sample (0)
|
||||
{
|
||||
|
|
@ -305,17 +323,29 @@ AudioTrigger::~AudioTrigger ()
|
|||
}
|
||||
|
||||
void
|
||||
AudioTrigger::set_start (timepos_t s)
|
||||
AudioTrigger::set_start (timepos_t const & s)
|
||||
{
|
||||
_start_offset = s.samples ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioTrigger::set_end (timepos_t e)
|
||||
AudioTrigger::set_end (timepos_t const & e)
|
||||
{
|
||||
set_length (timepos_t (e.samples() - _start_offset));
|
||||
}
|
||||
|
||||
void
|
||||
AudioTrigger::set_legato_offset (timepos_t const & offset)
|
||||
{
|
||||
_legato_offset = offset.samples();
|
||||
}
|
||||
|
||||
timepos_t
|
||||
AudioTrigger::current_pos() const
|
||||
{
|
||||
return timepos_t (read_index);
|
||||
}
|
||||
|
||||
timepos_t
|
||||
AudioTrigger::end() const
|
||||
{
|
||||
|
|
@ -549,6 +579,9 @@ AudioTrigger::load_data (boost::shared_ptr<AudioRegion> ar)
|
|||
data.push_back (new Sample[data_length]);
|
||||
ar->read (data[n], 0, data_length, n);
|
||||
}
|
||||
|
||||
set_name (ar->name());
|
||||
|
||||
} catch (...) {
|
||||
drop_data ();
|
||||
return -1;
|
||||
|
|
@ -560,7 +593,7 @@ AudioTrigger::load_data (boost::shared_ptr<AudioRegion> ar)
|
|||
void
|
||||
AudioTrigger::retrigger ()
|
||||
{
|
||||
read_index = _start_offset;
|
||||
read_index = _start_offset + _legato_offset;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -618,6 +651,7 @@ AudioTrigger::run (BufferSet& bufs, pframes_t nframes, pframes_t dest_offset, bo
|
|||
}
|
||||
}
|
||||
_state = Stopped;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, now stopped\n", index()));
|
||||
break;
|
||||
}
|
||||
|
|
@ -629,6 +663,7 @@ AudioTrigger::run (BufferSet& bufs, pframes_t nframes, pframes_t dest_offset, bo
|
|||
if (_state == Stopping && long_enough_to_fade) {
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 was stopping, now stopped\n", index()));
|
||||
_state = Stopped;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -643,6 +678,8 @@ Trigger::make_property_quarks ()
|
|||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for running = %1\n", Properties::running.property_id));
|
||||
}
|
||||
|
||||
const size_t TriggerBox::default_triggers_per_box = 8;
|
||||
|
||||
TriggerBox::TriggerBox (Session& s, DataType dt)
|
||||
: Processor (s, _("TriggerBox"), Temporal::BeatTime)
|
||||
, _bang_queue (1024)
|
||||
|
|
@ -653,7 +690,7 @@ TriggerBox::TriggerBox (Session& s, DataType dt)
|
|||
/* default number of possible triggers. call ::add_trigger() to increase */
|
||||
|
||||
if (_data_type == DataType::AUDIO) {
|
||||
for (size_t n = 0; n < 16; ++n) {
|
||||
for (size_t n = 0; n < default_triggers_per_box; ++n) {
|
||||
all_triggers.push_back (new AudioTrigger (n, *this));
|
||||
}
|
||||
}
|
||||
|
|
@ -964,6 +1001,9 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||
|
||||
if (nxt >= 0 && (size_t) nxt < all_triggers.size() && !all_triggers[nxt]->active()) {
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 switching to %2\n", trigger.index(), nxt));
|
||||
if (all_triggers[nxt]->legato()) {
|
||||
all_triggers[nxt]->set_legato_offset (trigger.current_pos());
|
||||
}
|
||||
/* start it up */
|
||||
all_triggers[nxt]->bang ();
|
||||
all_triggers[nxt]->process_state_requests ();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue