13
0

Fix loop recording alignment

DiskWriter::transport_looped() is called from the session
when engine loops. This does not take local disk-reader run()
latency offset into account.

finish_capture() needs to be postponed until the disk-writer
itself reaches the loop-position. This is achieved by
postponing loop() and calling it once loop-length of samples
has been captured.

This works because engaging loop always seeks to the loop-position
and first loop resets _capture_captured.
This commit is contained in:
Robin Gareus 2020-01-29 01:22:48 +01:00
parent eb7297e2fc
commit 6bc4f69c5c
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 41 additions and 9 deletions

View File

@ -169,6 +169,8 @@ private:
void check_record_status (samplepos_t transport_sample, double speed, bool can_record);
void finish_capture (boost::shared_ptr<ChannelList> c);
void loop (samplepos_t);
CaptureInfos capture_info;
mutable Glib::Threads::Mutex capture_info_lock;
@ -187,6 +189,9 @@ private:
volatile gint _num_captured_loops;
samplepos_t _accumulated_capture_offset;
bool _transport_looped;
samplepos_t _transport_loop_sample;
boost::shared_ptr<SMFSource> _midi_write_source;
std::list<boost::shared_ptr<Source> > _last_capture_sources;

View File

@ -59,6 +59,8 @@ DiskWriter::DiskWriter (Session& s, string const & str, DiskIOProcessor::Flag f)
, _samples_pending_write (0)
, _num_captured_loops (0)
, _accumulated_capture_offset (0)
, _transport_looped (false)
, _transport_loop_sample (0)
, _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
{
DiskIOProcessor::init ();
@ -397,6 +399,29 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
_need_butler = false;
const Location* const loop_loc = _loop_location;
samplepos_t loop_start = 0;
samplepos_t loop_end = 0;
samplepos_t loop_length = 0;
if (_transport_looped && _capture_captured == 0) {
_transport_looped = false;
}
if (loop_loc) {
get_location_times (loop_loc, &loop_start, &loop_end, &loop_length);
if (_was_recording && _transport_looped && _capture_captured >= loop_length) {
samplecnt_t remain = _capture_captured - loop_length;
_capture_captured = loop_length;
loop (_transport_loop_sample);
_capture_captured = remain;
}
} else {
_transport_looped = false;
}
#ifndef NDEBUG
if (speed != 0 && re) {
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: run() start: %2 end: %3 NF: %4\n", _name, start_sample, end_sample, nframes));
@ -418,15 +443,6 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
_last_recordable_sample = max_samplepos;
}
const Location* const loop_loc = _loop_location;
samplepos_t loop_start = 0;
samplepos_t loop_end = 0;
samplepos_t loop_length = 0;
if (loop_loc) {
get_location_times (loop_loc, &loop_start, &loop_end, &loop_length);
}
if (nominally_recording || (re && _was_recording && _session.get_record_enabled() && punch_in)) {
Evoral::OverlapType ot = Evoral::coverage (_first_recordable_sample, _last_recordable_sample, start_sample, end_sample);
@ -1318,6 +1334,17 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
void
DiskWriter::transport_looped (samplepos_t transport_sample)
{
if (_capture_captured) {
_transport_looped = true;
_transport_loop_sample = transport_sample;
_first_recordable_sample = transport_sample;
}
}
void
DiskWriter::loop (samplepos_t transport_sample)
{
_transport_looped = false;
if (_was_recording) {
// all we need to do is finish this capture, with modified capture length
boost::shared_ptr<ChannelList> c = channels.reader();