13
0

triggerbox: add "final sample" concept to start dealing with post-data playout

This commit is contained in:
Paul Davis 2022-01-07 12:46:04 -07:00
parent 1afc0ce69c
commit dbb816b1f9
2 changed files with 54 additions and 7 deletions

View File

@ -95,7 +95,11 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
* during the current call to ::run(). By the end of that call, it will * during the current call to ::run(). By the end of that call, it will
* have transitioned to Stopped. * have transitioned to Stopped.
*/ */
Stopping Stopping,
/* a Trigger in this state has played all of its data and is
* now silent-filling until we reach the "true end" of the trigger
*/
Playout,
}; };
Trigger (uint32_t index, TriggerBox&); Trigger (uint32_t index, TriggerBox&);
@ -363,7 +367,8 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
/* computed after data is reset */ /* computed after data is reset */
samplecnt_t usable_length; samplecnt_t usable_length;
samplepos_t last_sample; samplepos_t last_sample; /* where the data runs out */
samplepos_t final_sample; /* where we stop playing */
/* computed during run */ /* computed during run */

View File

@ -499,6 +499,7 @@ Trigger::process_state_requests (BufferSet& bufs, pframes_t dest_offset)
switch (_state) { switch (_state) {
case Running: case Running:
case Playout:
switch (launch_style()) { switch (launch_style()) {
case OneShot: case OneShot:
/* do nothing, just let it keep playing */ /* do nothing, just let it keep playing */
@ -543,6 +544,7 @@ Trigger::process_state_requests (BufferSet& bufs, pframes_t dest_offset)
switch (_state) { switch (_state) {
case Running: case Running:
case Playout:
begin_stop (true); begin_stop (true);
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 unbanged, now in WaitingToStop\n", index())); DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 unbanged, now in WaitingToStop\n", index()));
break; break;
@ -859,6 +861,7 @@ AudioTrigger::set_state (const XMLNode& node, int version)
node.get_property (X_("length"), t); node.get_property (X_("length"), t);
usable_length = t.samples(); usable_length = t.samples();
last_sample = _start_offset + usable_length; last_sample = _start_offset + usable_length;
final_sample = _start_offset + usable_length;
return 0; return 0;
} }
@ -907,6 +910,7 @@ AudioTrigger::set_usable_length ()
default: default:
usable_length = data.length; usable_length = data.length;
last_sample = _start_offset + usable_length; last_sample = _start_offset + usable_length;
final_sample = last_sample;
return; return;
} }
@ -915,6 +919,7 @@ AudioTrigger::set_usable_length ()
if (q == Temporal::BBT_Offset ()) { if (q == Temporal::BBT_Offset ()) {
usable_length = data.length; usable_length = data.length;
last_sample = _start_offset + usable_length; last_sample = _start_offset + usable_length;
final_sample = last_sample;
return; return;
} }
@ -923,6 +928,7 @@ AudioTrigger::set_usable_length ()
timecnt_t len (Temporal::Beats (q.beats, q.ticks), timepos_t (Temporal::Beats())); timecnt_t len (Temporal::Beats (q.beats, q.ticks), timepos_t (Temporal::Beats()));
usable_length = len.samples(); usable_length = len.samples();
last_sample = _start_offset + usable_length; last_sample = _start_offset + usable_length;
final_sample = last_sample;
// std::cerr << name() << " SUL ul " << usable_length << " of " << data.length << " so " << _start_offset << " ls " << last_sample << std::endl; // std::cerr << name() << " SUL ul " << usable_length << " of " << data.length << " so " << _start_offset << " ls " << last_sample << std::endl;
} }
@ -1175,6 +1181,7 @@ AudioTrigger::load_data (boost::shared_ptr<AudioRegion> ar)
if (!usable_length || usable_length > data.length) { if (!usable_length || usable_length > data.length) {
usable_length = data.length; usable_length = data.length;
last_sample = _start_offset + usable_length; last_sample = _start_offset + usable_length;
final_sample = last_sample;
} }
drop_data (); drop_data ();
@ -1233,6 +1240,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
/* did everything we could do */ /* did everything we could do */
return nframes; return nframes;
case Running: case Running:
case Playout:
case WaitingToStop: case WaitingToStop:
case Stopping: case Stopping:
/* stuff to do */ /* stuff to do */
@ -1298,7 +1306,7 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
} }
} }
while (nframes) { while (nframes && (_state != Playout)) {
pframes_t to_stretcher; pframes_t to_stretcher;
pframes_t from_stretcher; pframes_t from_stretcher;
@ -1414,19 +1422,53 @@ AudioTrigger::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
avail = _stretcher->available (); avail = _stretcher->available ();
dest_offset += from_stretcher; dest_offset += from_stretcher;
if (read_index >= last_sample && (_apparent_tempo == 0. || avail <= 0)) { if (read_index >= last_sample && (!do_stretch || avail <= 0)) {
if (last_sample < final_sample) {
_state = Playout;
} else {
_state = Stopped; _state = Stopped;
_loop_cnt++; _loop_cnt++;
}
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, now stopped, retrieved %2, avail %3\n", index(), retrieved, avail)); DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 reached end, now stopped, retrieved %2, avail %3\n", index(), retrieved, avail));
break; break;
} }
} }
pframes_t covered_frames = orig_nframes - nframes;
if (_state == Playout) {
const pframes_t remaining_frames_for_run= orig_nframes - covered_frames;
const pframes_t remaining_frames_till_final = final_sample - read_index;
const pframes_t to_fill = std::min (remaining_frames_till_final, remaining_frames_for_run);
for (uint32_t chn = 0; chn < bufs.count().n_audio(); ++chn) {
uint32_t channel = chn % data.size();
AudioBuffer& buf (bufs.get_audio (chn));
buf.silence (to_fill, dest_offset + covered_frames);
}
read_index += to_fill;
covered_frames += to_fill;
if (read_index < final_sample) {
/* more playout to be done */
return covered_frames;
}
_state == Stopped;
_loop_cnt++;
}
if (_state == Stopped || _state == Stopping) { if (_state == Stopped || _state == Stopping) {
when_stopped_during_run (bufs, dest_offset); when_stopped_during_run (bufs, dest_offset);
} }
return orig_nframes - nframes; return covered_frames;
} }
void void