triggerbox: add stretching property, virtualize computation of expected end sample, maybe fix position_as_fraction()
This commit is contained in:
parent
da00c50271
commit
71f7f7a09b
@ -129,6 +129,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
||||
virtual void reload (BufferSet&, void*) = 0;
|
||||
|
||||
virtual double position_as_fraction() const = 0;
|
||||
virtual void set_expected_end_sample (Temporal::TempoMap::SharedPtr const &, Temporal::BBT_Time const &) = 0;
|
||||
|
||||
void set_use_follow (bool yn);
|
||||
bool use_follow() const { return _use_follow; }
|
||||
@ -256,6 +257,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
||||
PBD::Property<float> _midi_velocity_effect;
|
||||
void* _ui;
|
||||
samplepos_t expected_end_sample;
|
||||
PBD::Property<bool> _stretching;
|
||||
|
||||
void set_region_internal (boost::shared_ptr<Region>);
|
||||
virtual void retrigger() = 0;
|
||||
@ -292,13 +294,17 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
|
||||
RubberBand::RubberBandStretcher* stretcher() { return (_stretcher); }
|
||||
|
||||
SegmentDescriptor get_segment_descriptor () const;
|
||||
void set_expected_end_sample (Temporal::TempoMap::SharedPtr const &, Temporal::BBT_Time const &);
|
||||
|
||||
void set_stretching (bool yn);
|
||||
bool stretching () const;
|
||||
|
||||
protected:
|
||||
void retrigger ();
|
||||
void set_usable_length ();
|
||||
|
||||
private:
|
||||
PBD::ID data_source;
|
||||
PBD::ID data_source;
|
||||
std::vector<Sample*> data;
|
||||
samplecnt_t read_index;
|
||||
samplecnt_t process_index;
|
||||
@ -309,9 +315,9 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
|
||||
samplepos_t last_sample;
|
||||
samplecnt_t retrieved;
|
||||
RubberBand::RubberBandStretcher* _stretcher;
|
||||
samplecnt_t got_stretcher_padding;
|
||||
samplecnt_t to_pad;
|
||||
samplecnt_t to_drop;
|
||||
samplecnt_t got_stretcher_padding;
|
||||
samplecnt_t to_pad;
|
||||
samplecnt_t to_drop;
|
||||
|
||||
void drop_data ();
|
||||
int load_data (boost::shared_ptr<AudioRegion>);
|
||||
@ -349,6 +355,7 @@ class LIBARDOUR_API MIDITrigger : public Trigger {
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
SegmentDescriptor get_segment_descriptor () const;
|
||||
void set_expected_end_sample (Temporal::TempoMap::SharedPtr const &, Temporal::BBT_Time const &);
|
||||
|
||||
protected:
|
||||
void retrigger ();
|
||||
@ -603,6 +610,7 @@ namespace Properties {
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<float> velocity_effect;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<gain_t> gain;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<Trigger*> currently_playing;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> stretching;
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,6 +56,7 @@ namespace ARDOUR {
|
||||
PBD::PropertyDescriptor<int> follow_action_probability;
|
||||
PBD::PropertyDescriptor<float> velocity_effect;
|
||||
PBD::PropertyDescriptor<gain_t> gain;
|
||||
PBD::PropertyDescriptor<bool> stretching;
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +81,14 @@ Trigger::Trigger (uint64_t n, TriggerBox& b)
|
||||
, _midi_velocity_effect (Properties::velocity_effect, 0.)
|
||||
, _ui (0)
|
||||
, expected_end_sample (0)
|
||||
, _stretching (Properties::stretching, true)
|
||||
{
|
||||
add_property (_legato);
|
||||
add_property (_use_follow);
|
||||
add_property (_follow_count);
|
||||
add_property (_midi_velocity_effect);
|
||||
add_property (_follow_action_probability);
|
||||
add_property (_stretching);
|
||||
}
|
||||
|
||||
void
|
||||
@ -368,8 +371,7 @@ Trigger::process_state_requests ()
|
||||
case Toggle:
|
||||
case Repeat:
|
||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 %2 gate/toggle/repeat => %3\n", index(), enum_2_string (Running), enum_2_string (WaitingToStop)));
|
||||
_state = WaitingToStop;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
begin_stop ();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -480,7 +482,7 @@ Trigger::maybe_compute_next_transition (samplepos_t start_sample, Temporal::Beat
|
||||
case WaitingToStart:
|
||||
retrigger ();
|
||||
_state = Running;
|
||||
expected_end_sample = tmap->sample_at (tmap->bbt_walk(transition_bbt, BBT_Offset (round (_barcnt), 0, 0)));
|
||||
set_expected_end_sample (tmap, transition_bbt);
|
||||
cerr << "starting at " << transition_bbt << " bars " << round(_barcnt) << " end at " << tmap->bbt_walk (transition_bbt, BBT_Offset (round (_barcnt), 0, 0)) << " sample = " << expected_end_sample << endl;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
|
||||
@ -499,7 +501,7 @@ Trigger::maybe_compute_next_transition (samplepos_t start_sample, Temporal::Beat
|
||||
case WaitingForRetrigger:
|
||||
retrigger ();
|
||||
_state = Running;
|
||||
expected_end_sample = tmap->sample_at (tmap->bbt_walk(transition_bbt, BBT_Offset (round (_barcnt), 0, 0)));
|
||||
set_expected_end_sample (tmap, transition_bbt);
|
||||
cerr << "starting at " << transition_bbt << " bars " << round(_barcnt) << " end at " << tmap->bbt_walk (transition_bbt, BBT_Offset (round (_barcnt), 0, 0)) << " sample = " << expected_end_sample << endl;
|
||||
PropertyChanged (ARDOUR::Properties::running);
|
||||
|
||||
@ -553,6 +555,22 @@ AudioTrigger::~AudioTrigger ()
|
||||
delete _stretcher;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioTrigger::stretching() const
|
||||
{
|
||||
return (_apparent_tempo != .0) && _stretching;
|
||||
}
|
||||
|
||||
void
|
||||
AudioTrigger::set_expected_end_sample (Temporal::TempoMap::SharedPtr const & tmap, Temporal::BBT_Time const & transition_bbt)
|
||||
{
|
||||
if (stretching()) {
|
||||
expected_end_sample = tmap->sample_at (tmap->bbt_walk(transition_bbt, Temporal::BBT_Offset (round (_barcnt), 0, 0)));
|
||||
} else {
|
||||
expected_end_sample = transition_samples = usable_length;
|
||||
}
|
||||
}
|
||||
|
||||
SegmentDescriptor
|
||||
AudioTrigger::get_segment_descriptor () const
|
||||
{
|
||||
@ -592,7 +610,7 @@ AudioTrigger::position_as_fraction () const
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return process_index / (double) usable_length;
|
||||
return process_index / (double) (expected_end_sample - transition_samples);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
@ -904,7 +922,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
|
||||
int avail = 0;
|
||||
BufferSet& scratch (_box.session().get_scratch_buffers (ChanCount (DataType::AUDIO, nchans)));
|
||||
std::vector<Sample*> bufp(nchans);
|
||||
const bool stretching = (_apparent_tempo != 0.);
|
||||
const bool do_stretch = stretching();
|
||||
|
||||
/* see if we're going to start or stop or retrigger in this run() call */
|
||||
pframes_t extra_offset = maybe_compute_next_transition (start_sample, start, end, dest_offset, passthru);
|
||||
@ -919,7 +937,6 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
|
||||
case WaitingForRetrigger:
|
||||
case WaitingToStart:
|
||||
/* did everything we could do */
|
||||
std::cerr << name() << " when i run, stretching will be: " << stretching << std::endl;
|
||||
return nframes;
|
||||
case Running:
|
||||
case WaitingToStop:
|
||||
@ -939,7 +956,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
|
||||
|
||||
/* tell the stretcher what we are doing for this ::run() call */
|
||||
|
||||
if (stretching) {
|
||||
if (do_stretch) {
|
||||
|
||||
const double stretch = _apparent_tempo / bpm;
|
||||
_stretcher->setTimeRatio (stretch);
|
||||
@ -992,7 +1009,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
|
||||
pframes_t to_stretcher;
|
||||
pframes_t from_stretcher;
|
||||
|
||||
if (stretching) {
|
||||
if (do_stretch) {
|
||||
|
||||
if (read_index < last_sample) {
|
||||
|
||||
@ -1068,7 +1085,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
|
||||
|
||||
uint64_t channel = chn % data.size();
|
||||
AudioBuffer& buf (bufs.get_audio (channel));
|
||||
Sample* src = stretching ? bufp[channel] : (data[channel] + read_index);
|
||||
Sample* src = do_stretch ? bufp[channel] : (data[channel] + read_index);
|
||||
|
||||
if (!passthru) {
|
||||
buf.read_from (src, from_stretcher, dest_offset);
|
||||
@ -1090,7 +1107,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
|
||||
* stretcher
|
||||
*/
|
||||
|
||||
if (!stretching) {
|
||||
if (!do_stretch) {
|
||||
read_index += from_stretcher;
|
||||
}
|
||||
|
||||
@ -1163,6 +1180,12 @@ MIDITrigger::~MIDITrigger ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MIDITrigger::set_expected_end_sample (Temporal::TempoMap::SharedPtr const & tmap, Temporal::BBT_Time const & transition_bbt)
|
||||
{
|
||||
expected_end_sample = tmap->sample_at (tmap->bbt_walk(transition_bbt, Temporal::BBT_Offset (round (_barcnt), 0, 0)));
|
||||
}
|
||||
|
||||
SegmentDescriptor
|
||||
MIDITrigger::get_segment_descriptor () const
|
||||
{
|
||||
@ -1525,6 +1548,8 @@ Trigger::make_property_quarks ()
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for follow-action-0 = %1\n", Properties::follow_action0.property_id));
|
||||
Properties::follow_action1.property_id = g_quark_from_static_string (X_("follow-action-1"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for follow-action-1 = %1\n", Properties::follow_action1.property_id));
|
||||
Properties::stretching.property_id = g_quark_from_static_string (X_("stretching"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for stretching = %1\n", Properties::stretching.property_id));
|
||||
}
|
||||
|
||||
const int32_t TriggerBox::default_triggers_per_box = 8;
|
||||
|
Loading…
Reference in New Issue
Block a user