triggerbox: allow setting of start to work correctly (for audio triggers)

This commit is contained in:
Paul Davis 2022-01-26 21:20:04 -07:00
parent fdf0c069ca
commit 0dc19a2b31
2 changed files with 41 additions and 38 deletions

View File

@ -436,15 +436,13 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
RubberBand::RubberBandStretcher* _stretcher;
samplepos_t _start_offset;
/* computed after data is reset */
samplepos_t last_sample; /* where the data runs out, relative to the start of the data, compare with read_index */
/* computed during run */
samplecnt_t read_index;
samplecnt_t process_index;
samplepos_t final_sample; /* where we stop playing, relative to the timeline */
samplepos_t last_readable_sample; /* where the data runs out, relative to the start of the data, compare with read_index */
samplepos_t final_processed_sample; /* where we stop playing, in process time, compare with process_index */
samplepos_t _legato_offset;
samplecnt_t retrieved;
samplecnt_t got_stretcher_padding;

View File

@ -820,9 +820,10 @@ AudioTrigger::AudioTrigger (uint32_t n, TriggerBox& b)
: Trigger (n, b)
, _stretcher (0)
, _start_offset (0)
, last_sample (0)
, read_index (0)
, process_index (0)
, last_readable_sample (0)
, final_processed_sample (0)
, _legato_offset (0)
, retrieved (0)
, got_stretcher_padding (false)
@ -949,7 +950,7 @@ void
AudioTrigger::set_start (timepos_t const & s)
{
/* XXX better minimum size needed */
_start_offset = std::min (samplepos_t (4096), s.samples ());
_start_offset = std::max (samplepos_t (4096), s.samples ());
}
void
@ -982,9 +983,9 @@ AudioTrigger::set_expected_end_sample (Temporal::TempoMap::SharedPtr const & tma
{
/* Our task here is to set:
expected_end_sample: the sample position where the data for the clip should run out (taking stretch into account)
last_sample: the sample in the data where we stop reading
final_sample: the sample where the trigger stops and the follow action if any takes effect
expected_end_sample: (TIMELINE!) the sample position where the data for the clip should run out (taking stretch into account)
last_readable_sample: the sample in the data where we stop reading
final_processed_sample: the sample where the trigger stops and the follow action if any takes effect
Things that affect these values:
@ -998,9 +999,9 @@ AudioTrigger::set_expected_end_sample (Temporal::TempoMap::SharedPtr const & tma
samplepos_t end_by_beatcnt = tmap->sample_at (tmap->bbt_walk(transition_bbt, Temporal::BBT_Offset (0, round (_beatcnt), 0))); //OK?
samplepos_t end_by_data_length = transition_sample + (data.length - _start_offset);
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 @ %2 / %3 / %4 ends: FL %5 (from %6) BC %7 DL %8\n",
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 SO %9 @ %2 / %3 / %4 ends: FL %5 (from %6) BC %7 DL %8\n",
index(), transition_sample, transition_beats, transition_bbt,
end_by_follow_length, _follow_length, end_by_beatcnt, end_by_data_length));
end_by_follow_length, _follow_length, end_by_beatcnt, end_by_data_length, _start_offset));
if (stretching()) {
if (internal_use_follow_length()) {
@ -1017,29 +1018,29 @@ AudioTrigger::set_expected_end_sample (Temporal::TempoMap::SharedPtr const & tma
}
if (internal_use_follow_length()) {
final_sample = end_by_follow_length - transition_sample;
final_processed_sample = end_by_follow_length - transition_sample;
} else {
final_sample = expected_end_sample - transition_sample;
final_processed_sample = expected_end_sample - transition_sample;
}
samplecnt_t usable_length;
if (internal_use_follow_length() && (end_by_follow_length < end_by_data_length)) {
usable_length = tmap->sample_at (tmap->bbt_walk (Temporal::BBT_Time (), _follow_length));
usable_length = end_by_follow_length - transition_samples;
} else {
usable_length = (data.length - _start_offset);
}
/* called from set_expected_end_sample() when we know the time (audio &
* musical time domains when we start starting. Our job here is to
* define the last_sample we can use as data.
* define the last_readable_sample we can use as data.
*/
Temporal::BBT_Offset q (_quantization);
if (launch_style() != Repeat || (q == Temporal::BBT_Offset())) {
last_sample = usable_length;
last_readable_sample = _start_offset + usable_length;
} else {
@ -1051,10 +1052,10 @@ AudioTrigger::set_expected_end_sample (Temporal::TempoMap::SharedPtr const & tma
/* XXX MUST HANDLE BAR-LEVEL QUANTIZATION */
timecnt_t len (Temporal::Beats (q.beats, q.ticks), timepos_t (Temporal::Beats()));
last_sample = _start_offset + len.samples();
last_readable_sample = _start_offset + len.samples();
}
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1: final sample %2 vs ees %3 ls %4\n", index(), final_sample, expected_end_sample, last_sample));
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1: final sample %2 vs ees %3 ls %4\n", index(), final_processed_sample, expected_end_sample, last_readable_sample));
}
void
@ -1470,14 +1471,14 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
if (do_stretch) {
if (read_index < last_sample) {
if (read_index < last_readable_sample) {
/* still have data to push into the stretcher */
to_stretcher = (pframes_t) std::min (samplecnt_t (rb_blocksize), (last_sample - read_index));
to_stretcher = (pframes_t) std::min (samplecnt_t (rb_blocksize), (last_readable_sample - read_index));
const bool at_end = (to_stretcher < rb_blocksize);
while ((pframes_t) avail < nframes && (read_index < last_sample)) {
while ((pframes_t) avail < nframes && (read_index < last_readable_sample)) {
/* keep feeding the stretcher in chunks of "to_stretcher",
* until there's nframes of data available, or we reach
* the end of the region
@ -1513,37 +1514,39 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
*/
from_stretcher = nframes;
// cerr << "FS#1 from nframes = " << from_stretcher << endl;
} else {
/* finished delivering data to stretcher, but may have not yet retrieved it all */
avail = _stretcher->available ();
from_stretcher = (pframes_t) std::min ((pframes_t) nframes, (pframes_t) avail);
// cerr << "FS#X from avail " << avail << " nf " << nframes << " = " << from_stretcher << endl;
}
/* fetch the stretch */
retrieved += _stretcher->retrieve (&bufp[0], from_stretcher);
if (read_index >= last_sample) {
if (read_index >= last_readable_sample) {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 no more data to deliver to stretcher, but retrieved %2 to put current end at %3 vs %4 / %5 pi %6\n",
index(), retrieved, transition_samples + retrieved, expected_end_sample, final_sample, process_index));
index(), retrieved, transition_samples + retrieved, expected_end_sample, final_processed_sample, process_index));
if (transition_samples + retrieved > expected_end_sample) {
/* final pull from stretched data into output buffers */
from_stretcher = std::min ((samplecnt_t) from_stretcher, expected_end_sample - process_index);
// cerr << "FS#2 from ees " << expected_end_sample << " - " << process_index << " = " << from_stretcher << endl;
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 total retrieved data %2 exceeds theoretical size %3, truncate from_stretcher to %4\n",
index(), retrieved, expected_end_sample - transition_samples, from_stretcher));
if (from_stretcher == 0) {
if (process_index < final_sample) {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached (EX) end, entering playout mode to cover %2 .. %3\n", index(), process_index, final_sample));
if (process_index < final_processed_sample) {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached (EX) end, entering playout mode to cover %2 .. %3\n", index(), process_index, final_processed_sample));
_state = Playout;
} else {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached (EX) end, now stopped, retrieved %2, avail %3 pi %4 vs fs %5\n", index(), retrieved, avail, process_index, final_sample));
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached (EX) end, now stopped, retrieved %2, avail %3 pi %4 vs fs %5\n", index(), retrieved, avail, process_index, final_processed_sample));
_state = Stopped;
_loop_cnt++;
}
@ -1556,10 +1559,12 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
} else {
/* no stretch */
from_stretcher = (pframes_t) std::min ((samplecnt_t) nframes, (last_sample - read_index));
from_stretcher = (pframes_t) std::min ((samplecnt_t) nframes, (last_readable_sample - read_index));
// cerr << "FS#3 from lrs " << last_readable_sample << " - " << read_index << " = " << from_stretcher << endl;
}
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 ready with %2 ri %3 ls %4, will write %5\n", name(), avail, read_index, last_sample, from_stretcher));
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 ready with %2 ri %3 ls %4, will write %5\n", name(), avail, read_index, last_readable_sample, from_stretcher));
/* deliver to buffers */
@ -1600,10 +1605,10 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
avail = _stretcher->available ();
dest_offset += from_stretcher;
if (read_index >= last_sample && (!do_stretch || avail <= 0)) {
if (read_index >= last_readable_sample && (!do_stretch || avail <= 0)) {
if (process_index < final_sample) {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, entering playout mode to cover %2 .. %3\n", index(), process_index, final_sample));
if (process_index < final_processed_sample) {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, entering playout mode to cover %2 .. %3\n", index(), process_index, final_processed_sample));
_state = Playout;
} else {
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, now stopped, retrieved %2, avail %3\n", index(), retrieved, avail));
@ -1627,11 +1632,11 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
}
const pframes_t remaining_frames_for_run= orig_nframes - covered_frames;
const pframes_t remaining_frames_till_final = final_sample - process_index;
const pframes_t remaining_frames_till_final = final_processed_sample - process_index;
const pframes_t to_fill = std::min (remaining_frames_till_final, remaining_frames_for_run);
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 playout mode, remaining in run %2 till final %3 @ %5 ts %7 vs pi @ %6 to fill %4\n",
index(), remaining_frames_for_run, remaining_frames_till_final, to_fill, final_sample, process_index, transition_samples));
index(), remaining_frames_for_run, remaining_frames_till_final, to_fill, final_processed_sample, process_index, transition_samples));
if (remaining_frames_till_final != 0) {
@ -1646,7 +1651,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
process_index += to_fill;
covered_frames += to_fill;
if (process_index < final_sample) {
if (process_index < final_processed_sample) {
/* more playout to be done */
return covered_frames;
}
@ -2044,11 +2049,11 @@ MIDITrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sam
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 not done with playout, all frames covered\n", index()));
} else {
/* finishing up playout */
samplepos_t final_sample = tmap->sample_at (timepos_t (final_beat));
nframes = orig_nframes - (final_sample - start_sample);
samplepos_t final_processed_sample = tmap->sample_at (timepos_t (final_beat));
nframes = orig_nframes - (final_processed_sample - start_sample);
_loop_cnt++;
_state = Stopped;
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 playout done, nf = %2 fb %3 fs %4 %5\n", index(), nframes, final_beat, final_sample, start_sample));
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 playout done, nf = %2 fb %3 fs %4 %5\n", index(), nframes, final_beat, final_processed_sample, start_sample));
}
}