13
0

Fix MIDI loop capture alignment

Loop recording creates a single long source, regions have to be
"split" from this source, using "start" as offset.

Since MIDI uses absolute timestamps, offsetting this by accumulating
 buffer_position += (*ci)->samples;
like Track::use_captured_audio_sources() does, is not correct.

Furthermore, record_enabled() may be off when stopping recording,
MIDI needs to be flushed regardless.
This commit is contained in:
Robin Gareus 2020-01-29 15:14:27 +01:00
parent ffe7fcd3b0
commit 0ab46c342f
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
3 changed files with 17 additions and 4 deletions

View File

@ -783,6 +783,7 @@ enum MidiTempoMapDisposition {
struct CaptureInfo {
samplepos_t start;
samplecnt_t samples;
samplecnt_t loop_offset;
};
enum LoopFadeChoice {

View File

@ -463,6 +463,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
*/
_capture_captured = start_sample - loop_start;
_capture_start_sample = loop_start;
_first_recordable_sample = loop_start;
if (_capture_captured > 0) {
/* when enabling record while already looping,
* zero fill region back to loop-start.
@ -695,6 +696,16 @@ DiskWriter::finish_capture (boost::shared_ptr<ChannelList> c)
ci->start = _capture_start_sample;
ci->samples = _capture_captured;
if (_loop_location) {
samplepos_t loop_start = 0;
samplepos_t loop_end = 0;
samplepos_t loop_length = 0;
get_location_times (_loop_location, &loop_start, &loop_end, &loop_length);
ci->loop_offset = _num_captured_loops * loop_length;
} else {
ci->loop_offset = 0;
}
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("Finish capture, add new CI, %1 + %2\n", ci->start, ci->samples));
/* XXX theoretical race condition here. Need atomic exchange ?
@ -1024,7 +1035,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
to_write = _chunk_samples;
}
if (record_enabled() && ((total > _chunk_samples) || force_flush)) {
if ((total > _chunk_samples) || force_flush) {
Source::Lock lm(_midi_write_source->mutex());
if (_midi_write_source->midi_write (lm, *_midi_buf, get_capture_start_sample (0), to_write) != to_write) {
error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg;
@ -1348,7 +1359,6 @@ DiskWriter::transport_looped (samplepos_t transport_sample)
if (_capture_captured) {
_transport_looped = true;
_transport_loop_sample = transport_sample;
_first_recordable_sample = transport_sample;
}
}

View File

@ -977,15 +977,17 @@ Track::use_captured_midi_sources (SourceList& srcs, CaptureInfos const & capture
_name, (*ci)->start, (*ci)->samples, region_name));
// cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->samples << " add a region\n";
// cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->samples << " start: " << (*ci)->loop_offset << " add MIDI region\n";
try {
PropertyList plist;
/* start of this region is the offset between the start of its capture and the start of the whole pass */
plist.add (Properties::start, (*ci)->start - initial_capture);
samplecnt_t start_off = (*ci)->start - initial_capture + (*ci)->loop_offset;
plist.add (Properties::start, start_off);
plist.add (Properties::length, (*ci)->samples);
plist.add (Properties::length_beats, converter.from((*ci)->samples).to_double());
plist.add (Properties::start_beats, converter.from(start_off).to_double());
plist.add (Properties::name, region_name);
boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));