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:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user