triggerbox: lots of design changes and implementation tweaks. Gate launch style now works
This commit is contained in:
parent
50d68a6a34
commit
8eed420ad4
@ -19,6 +19,7 @@
|
|||||||
#ifndef __ardour_triggerbox_h__
|
#ifndef __ardour_triggerbox_h__
|
||||||
#define __ardour_triggerbox_h__
|
#define __ardour_triggerbox_h__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@ -42,10 +43,12 @@ class TriggerBox;
|
|||||||
|
|
||||||
class LIBARDOUR_API Trigger {
|
class LIBARDOUR_API Trigger {
|
||||||
public:
|
public:
|
||||||
Trigger();
|
Trigger (boost::shared_ptr<Region>);
|
||||||
virtual ~Trigger() {}
|
virtual ~Trigger() {}
|
||||||
|
|
||||||
virtual void bang (TriggerBox&, Temporal::Beats const &, samplepos_t) = 0;
|
virtual void bang (TriggerBox&, Temporal::Beats const &, samplepos_t) = 0;
|
||||||
|
virtual void unbang (TriggerBox&, Temporal::Beats const &, samplepos_t) = 0;
|
||||||
|
|
||||||
bool running() const { return _running; }
|
bool running() const { return _running; }
|
||||||
|
|
||||||
enum LaunchStyle {
|
enum LaunchStyle {
|
||||||
@ -72,10 +75,17 @@ class LIBARDOUR_API Trigger {
|
|||||||
FollowAction follow_action() const { return _follow_action; }
|
FollowAction follow_action() const { return _follow_action; }
|
||||||
void set_follow_action (FollowAction);
|
void set_follow_action (FollowAction);
|
||||||
|
|
||||||
|
virtual int set_region (boost::shared_ptr<Region>) = 0;
|
||||||
|
boost::shared_ptr<Region> region() const { return _region; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _running;
|
bool _running;
|
||||||
|
bool _stop_requested;
|
||||||
LaunchStyle _launch_style;
|
LaunchStyle _launch_style;
|
||||||
FollowAction _follow_action;
|
FollowAction _follow_action;
|
||||||
|
boost::shared_ptr<Region> _region;
|
||||||
|
|
||||||
|
void set_region_internal (boost::shared_ptr<Region>);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LIBARDOUR_API AudioTrigger : public Trigger {
|
class LIBARDOUR_API AudioTrigger : public Trigger {
|
||||||
@ -84,13 +94,19 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
|
|||||||
~AudioTrigger ();
|
~AudioTrigger ();
|
||||||
|
|
||||||
void bang (TriggerBox&, Temporal::Beats const & , samplepos_t);
|
void bang (TriggerBox&, Temporal::Beats const & , samplepos_t);
|
||||||
|
void unbang (TriggerBox&, Temporal::Beats const & , samplepos_t);
|
||||||
|
|
||||||
Sample* run (uint32_t channel, pframes_t& nframes, samplepos_t start_frame, samplepos_t end_frame, bool& need_butler);
|
Sample* run (uint32_t channel, pframes_t& nframes, samplepos_t start_frame, samplepos_t end_frame, bool& need_butler);
|
||||||
|
|
||||||
|
int set_region (boost::shared_ptr<Region>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<AudioRegion> region;
|
|
||||||
std::vector<Sample*> data;
|
std::vector<Sample*> data;
|
||||||
std::vector<samplecnt_t> read_index;
|
std::vector<samplecnt_t> read_index;
|
||||||
samplecnt_t length;
|
samplecnt_t length;
|
||||||
|
|
||||||
|
void drop_data ();
|
||||||
|
int load_data (boost::shared_ptr<AudioRegion>);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LIBARDOUR_API TriggerBox : public Processor
|
class LIBARDOUR_API TriggerBox : public Processor
|
||||||
@ -103,6 +119,10 @@ class LIBARDOUR_API TriggerBox : public Processor
|
|||||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
|
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
|
||||||
bool configure_io (ChanCount in, ChanCount out);
|
bool configure_io (ChanCount in, ChanCount out);
|
||||||
|
|
||||||
|
typedef std::vector<Trigger*> Triggers;
|
||||||
|
|
||||||
|
Trigger* trigger (Triggers::size_type);
|
||||||
|
|
||||||
bool queue_trigger (Trigger*);
|
bool queue_trigger (Trigger*);
|
||||||
void add_trigger (Trigger*);
|
void add_trigger (Trigger*);
|
||||||
|
|
||||||
@ -112,19 +132,18 @@ class LIBARDOUR_API TriggerBox : public Processor
|
|||||||
private:
|
private:
|
||||||
PBD::RingBuffer<Trigger*> _trigger_queue;
|
PBD::RingBuffer<Trigger*> _trigger_queue;
|
||||||
|
|
||||||
typedef std::vector<Trigger*> Triggers;
|
|
||||||
Triggers active_triggers;
|
Triggers active_triggers;
|
||||||
Glib::Threads::Mutex trigger_lock;
|
Glib::Threads::RWLock trigger_lock;
|
||||||
Triggers all_triggers;
|
Triggers all_triggers;
|
||||||
|
|
||||||
|
void drop_triggers ();
|
||||||
|
void process_trigger_requests (Temporal::Beats const &, samplepos_t);
|
||||||
|
|
||||||
void note_on (int note_number, int velocity);
|
void note_on (int note_number, int velocity);
|
||||||
void note_off (int note_number, int velocity);
|
void note_off (int note_number, int velocity);
|
||||||
|
|
||||||
/* XXX for initial testing only */
|
typedef std::map<uint8_t,Triggers::size_type> MidiTriggerMap;
|
||||||
|
MidiTriggerMap midi_trigger_map;
|
||||||
boost::shared_ptr<Source> the_source;
|
|
||||||
boost::shared_ptr<AudioRegion> the_region;
|
|
||||||
AudioTrigger* the_trigger;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "pbd/failed_constructor.h"
|
||||||
|
|
||||||
#include "ardour/audioregion.h"
|
#include "ardour/audioregion.h"
|
||||||
#include "ardour/audio_buffer.h"
|
#include "ardour/audio_buffer.h"
|
||||||
#include "ardour/midi_buffer.h"
|
#include "ardour/midi_buffer.h"
|
||||||
@ -17,9 +19,16 @@ TriggerBox::TriggerBox (Session& s)
|
|||||||
: Processor (s, _("TriggerBox"), Temporal::BeatTime)
|
: Processor (s, _("TriggerBox"), Temporal::BeatTime)
|
||||||
, _trigger_queue (1024)
|
, _trigger_queue (1024)
|
||||||
{
|
{
|
||||||
PropertyList plist;
|
|
||||||
|
|
||||||
the_source.reset (new SndFileSource (_session, "/music/misc/La_Voz_Del_Rio.wav", 0, Source::Flag (0)));
|
/* default number of possible triggers. call ::add_trigger() to increase */
|
||||||
|
|
||||||
|
all_triggers.resize (16, 0);
|
||||||
|
|
||||||
|
midi_trigger_map.insert (midi_trigger_map.end(), std::make_pair (uint8_t (60), 0));
|
||||||
|
|
||||||
|
boost::shared_ptr<Source> the_source (new SndFileSource (_session, "/music/misc/La_Voz_Del_Rio.wav", 0, Source::Flag (0)));
|
||||||
|
|
||||||
|
PropertyList plist;
|
||||||
|
|
||||||
plist.add (Properties::start, 0);
|
plist.add (Properties::start, 0);
|
||||||
plist.add (Properties::length, the_source->length ());
|
plist.add (Properties::length, the_source->length ());
|
||||||
@ -27,18 +36,39 @@ TriggerBox::TriggerBox (Session& s)
|
|||||||
plist.add (Properties::layer, 0);
|
plist.add (Properties::layer, 0);
|
||||||
plist.add (Properties::layering_index, 0);
|
plist.add (Properties::layering_index, 0);
|
||||||
|
|
||||||
boost::shared_ptr<Region> r = RegionFactory::create (the_source, plist, false);
|
boost::shared_ptr<Region> the_region (RegionFactory::create (the_source, plist, false));
|
||||||
the_region = boost::dynamic_pointer_cast<AudioRegion> (r);
|
|
||||||
|
|
||||||
/* XXX the_region/trigger will be looked up in a
|
all_triggers[0] = new AudioTrigger (boost::dynamic_pointer_cast<AudioRegion> (the_region));
|
||||||
std::map<MIDI::byte,Trigger>
|
|
||||||
*/
|
|
||||||
the_trigger = new AudioTrigger (the_region);
|
|
||||||
add_trigger (the_trigger);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TriggerBox::~TriggerBox ()
|
TriggerBox::~TriggerBox ()
|
||||||
{
|
{
|
||||||
|
drop_triggers ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TriggerBox::drop_triggers ()
|
||||||
|
{
|
||||||
|
Glib::Threads::RWLock::WriterLock lm (trigger_lock);
|
||||||
|
|
||||||
|
for (Triggers::iterator t = all_triggers.begin(); t != all_triggers.end(); ++t) {
|
||||||
|
if (*t) {
|
||||||
|
delete *t;
|
||||||
|
(*t) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger*
|
||||||
|
TriggerBox::trigger (Triggers::size_type n)
|
||||||
|
{
|
||||||
|
Glib::Threads::RWLock::ReaderLock lm (trigger_lock);
|
||||||
|
|
||||||
|
if (n >= all_triggers.size()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_triggers[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -56,16 +86,14 @@ TriggerBox::can_support_io_configuration (const ChanCount& in, ChanCount& out)
|
|||||||
bool
|
bool
|
||||||
TriggerBox::configure_io (ChanCount in, ChanCount out)
|
TriggerBox::configure_io (ChanCount in, ChanCount out)
|
||||||
{
|
{
|
||||||
cerr << "TB: " << in << " / " << out << endl;
|
|
||||||
return Processor::configure_io (in, out);
|
return Processor::configure_io (in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriggerBox::add_trigger (Trigger* trigger)
|
TriggerBox::add_trigger (Trigger* trigger)
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock lm (trigger_lock);
|
Glib::Threads::RWLock::WriterLock lm (trigger_lock);
|
||||||
all_triggers.push_back (trigger);
|
all_triggers.push_back (trigger);
|
||||||
cerr << "Now have " << all_triggers.size() << " of all possible triggers\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -74,29 +102,86 @@ TriggerBox::queue_trigger (Trigger* trigger)
|
|||||||
return _trigger_queue.write (&trigger, 1) == 1;
|
return _trigger_queue.write (&trigger, 1) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TriggerBox::process_trigger_requests (Temporal::Beats const & beats_now, samplepos_t samples_now)
|
||||||
|
{
|
||||||
|
/* if there are any triggers queued, make them active
|
||||||
|
*/
|
||||||
|
|
||||||
|
RingBuffer<Trigger*>::rw_vector vec;
|
||||||
|
_trigger_queue.get_read_vector (&vec);
|
||||||
|
|
||||||
|
for (uint32_t n = 0; n < vec.len[0]; ++n) {
|
||||||
|
Trigger* t = vec.buf[0][n];
|
||||||
|
t->bang (*this, beats_now, samples_now);
|
||||||
|
active_triggers.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t n = 0; n < vec.len[1]; ++n) {
|
||||||
|
Trigger* t = vec.buf[1][n];
|
||||||
|
t->bang (*this, beats_now, samples_now);
|
||||||
|
active_triggers.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
_trigger_queue.increment_read_idx (vec.len[0] + vec.len[1]);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required)
|
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;
|
samplepos_t next_beat = 0;
|
||||||
Temporal::Beats beats_now;
|
Temporal::Beats beats_now;
|
||||||
|
|
||||||
|
process_trigger_requests (beats_now, start_sample);
|
||||||
|
|
||||||
/* check MIDI port input buffers for triggers */
|
/* check MIDI port input buffers for triggers */
|
||||||
|
|
||||||
for (BufferSet::midi_iterator mi = bufs.midi_begin(); mi != bufs.midi_end(); ++mi) {
|
for (BufferSet::midi_iterator mi = bufs.midi_begin(); mi != bufs.midi_end(); ++mi) {
|
||||||
MidiBuffer& mb (*mi);
|
MidiBuffer& mb (*mi);
|
||||||
|
|
||||||
for (MidiBuffer::iterator ev = mb.begin(); ev != mb.end(); ++ev) {
|
for (MidiBuffer::iterator ev = mb.begin(); ev != mb.end(); ++ev) {
|
||||||
|
|
||||||
|
if (!(*ev).is_note()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiTriggerMap::iterator mt = midi_trigger_map.find ((*ev).note());
|
||||||
|
Trigger* t = 0;
|
||||||
|
|
||||||
|
if (mt != midi_trigger_map.end()) {
|
||||||
|
|
||||||
|
assert (mt->second < all_triggers.size());
|
||||||
|
|
||||||
|
t = all_triggers[mt->second];
|
||||||
|
|
||||||
|
if (!t) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((*ev).is_note_on()) {
|
if ((*ev).is_note_on()) {
|
||||||
|
|
||||||
if (!the_trigger->running()) {
|
if (!t->running()) {
|
||||||
active_triggers.push_back (the_trigger);
|
active_triggers.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
t->bang (*this, beats_now, start_sample);
|
||||||
|
|
||||||
|
} else if ((*ev).is_note_off()) {
|
||||||
|
|
||||||
|
if (t->running() && t->launch_style() == Trigger::Gate) {
|
||||||
|
t->unbang (*this, beats_now, start_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
the_trigger->bang (*this, beats_now, start_sample);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (active_triggers.empty()) {
|
||||||
|
/* nothing to do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* get tempo map */
|
/* get tempo map */
|
||||||
|
|
||||||
/* find offset to next bar * and beat start
|
/* find offset to next bar * and beat start
|
||||||
@ -112,34 +197,9 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||||||
//run_beats = true;
|
//run_beats = true;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/* if there are any triggers queued, make them active
|
|
||||||
*/
|
|
||||||
|
|
||||||
RingBuffer<Trigger*>::rw_vector vec;
|
|
||||||
_trigger_queue.get_read_vector (&vec);
|
|
||||||
|
|
||||||
for (uint32_t n = 0; n < vec.len[0]; ++n) {
|
|
||||||
Trigger* t = vec.buf[0][n];
|
|
||||||
t->bang (*this, beats_now, start_sample);
|
|
||||||
active_triggers.push_back (t);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
_trigger_queue.increment_read_idx (vec.len[0] + vec.len[1]);
|
|
||||||
|
|
||||||
bool err = false;
|
bool err = false;
|
||||||
const size_t nchans = the_region->n_channels ();
|
|
||||||
bool need_butler = false;
|
bool need_butler = false;
|
||||||
|
size_t max_chans = 0;
|
||||||
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) {
|
for (Triggers::iterator t = active_triggers.begin(); !err && t != active_triggers.end(); ++t) {
|
||||||
|
|
||||||
@ -149,6 +209,10 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (at->region());
|
||||||
|
const size_t nchans = ar->n_channels ();
|
||||||
|
max_chans = std::max (max_chans, nchans);
|
||||||
|
|
||||||
for (uint32_t chan = 0; !err && chan < nchans; ++chan) {
|
for (uint32_t chan = 0; !err && chan < nchans; ++chan) {
|
||||||
|
|
||||||
AudioBuffer& buf = bufs.get_audio (chan);
|
AudioBuffer& buf = bufs.get_audio (chan);
|
||||||
@ -158,7 +222,6 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
/* XXX need to delete the trigger/put it back in the pool */
|
/* XXX need to delete the trigger/put it back in the pool */
|
||||||
cerr << "trigger complete\n";
|
|
||||||
t = active_triggers.erase (t);
|
t = active_triggers.erase (t);
|
||||||
err = true;
|
err = true;
|
||||||
} else {
|
} else {
|
||||||
@ -175,7 +238,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChanCount cc (DataType::AUDIO, nchans);
|
ChanCount cc (DataType::AUDIO, max_chans);
|
||||||
cc.set_midi (bufs.count().n_midi());
|
cc.set_midi (bufs.count().n_midi());
|
||||||
bufs.set_count (cc);
|
bufs.set_count (cc);
|
||||||
}
|
}
|
||||||
@ -192,33 +255,46 @@ TriggerBox::set_state (const XMLNode&, int version)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*--------------------*/
|
/*--------------------*/
|
||||||
|
|
||||||
Trigger::Trigger ()
|
Trigger::Trigger (boost::shared_ptr<Region> r)
|
||||||
: _running (false)
|
: _running (false)
|
||||||
, _launch_style (Loop)
|
, _stop_requested (false)
|
||||||
|
, _launch_style (Gate)
|
||||||
, _follow_action (Stop)
|
, _follow_action (Stop)
|
||||||
|
, _region (r)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Trigger::set_follow_action (FollowAction f)
|
||||||
|
{
|
||||||
|
_follow_action = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Trigger::set_launch_style (LaunchStyle l)
|
||||||
|
{
|
||||||
|
_launch_style = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Trigger::set_region_internal (boost::shared_ptr<Region> r)
|
||||||
|
{
|
||||||
|
_region = r;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------*/
|
/*--------------------*/
|
||||||
|
|
||||||
AudioTrigger::AudioTrigger (boost::shared_ptr<AudioRegion> r)
|
AudioTrigger::AudioTrigger (boost::shared_ptr<AudioRegion> r)
|
||||||
: region (r)
|
: Trigger (r)
|
||||||
, data (0)
|
, data (0)
|
||||||
, length (0)
|
, length (0)
|
||||||
{
|
{
|
||||||
/* XXX catch region going away */
|
/* XXX catch region going away */
|
||||||
|
|
||||||
const uint32_t nchans = region->n_channels();
|
if (load_data (r)) {
|
||||||
|
throw failed_constructor ();
|
||||||
length = region->length_samples();
|
|
||||||
|
|
||||||
for (uint32_t n = 0; n < nchans; ++n) {
|
|
||||||
data.push_back (new Sample[length]);;
|
|
||||||
read_index.push_back (0);
|
|
||||||
region->read (data[n], 0, length, n);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +305,56 @@ AudioTrigger::~AudioTrigger ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AudioTrigger::set_region (boost::shared_ptr<Region> r)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
|
||||||
|
|
||||||
|
if (!ar) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_region_internal (r);
|
||||||
|
|
||||||
|
if (load_data (ar)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioTrigger::drop_data ()
|
||||||
|
{
|
||||||
|
for (uint32_t n = 0; n < data.size(); ++n) {
|
||||||
|
delete [] data[n];
|
||||||
|
}
|
||||||
|
data.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AudioTrigger::load_data (boost::shared_ptr<AudioRegion> ar)
|
||||||
|
{
|
||||||
|
const uint32_t nchans = ar->n_channels();
|
||||||
|
|
||||||
|
length = ar->length_samples();
|
||||||
|
|
||||||
|
drop_data ();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (uint32_t n = 0; n < nchans; ++n) {
|
||||||
|
data.push_back (new Sample[length]);
|
||||||
|
read_index.push_back (0);
|
||||||
|
ar->read (data[n], 0, length, n);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
drop_data ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioTrigger::bang (TriggerBox& /*proc*/, Temporal::Beats const &, samplepos_t)
|
AudioTrigger::bang (TriggerBox& /*proc*/, Temporal::Beats const &, samplepos_t)
|
||||||
{
|
{
|
||||||
@ -243,6 +369,12 @@ AudioTrigger::bang (TriggerBox& /*proc*/, Temporal::Beats const &, samplepos_t)
|
|||||||
_running = true;
|
_running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioTrigger::unbang (TriggerBox& /*proc*/, Temporal::Beats const &, samplepos_t)
|
||||||
|
{
|
||||||
|
_stop_requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
Sample*
|
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 */)
|
||||||
{
|
{
|
||||||
@ -251,6 +383,14 @@ AudioTrigger::run (uint32_t channel, pframes_t& nframes, samplepos_t /*start_sam
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (read_index[channel] >= length) {
|
if (read_index[channel] >= length) {
|
||||||
|
_running = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stop_requested) {
|
||||||
|
/* XXX need fade out machinery */
|
||||||
|
_running = false;
|
||||||
|
_stop_requested = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user