framepos_t loop_start = 0;
framepos_t loop_end = 0;
framepos_t loop_length = 0;
- get_location_times(loop_loc, &loop_start, &loop_end, &loop_length);
+
+ get_location_times (loop_loc, &loop_start, &loop_end, &loop_length);
adjust_capture_position = 0;
playback_distance = nframes;
}
- if (need_disk_signal) {
+ if (need_disk_signal && !_session.declick_out_pending()) {
/* copy the diskstream data to all output buffers */
MidiBuffer& mbuf (bufs.get_midi (0));
MidiDiskstream::read (framepos_t& start, framecnt_t dur, bool reversed)
{
framecnt_t this_read = 0;
- bool reloop = false;
framepos_t loop_end = 0;
framepos_t loop_start = 0;
framecnt_t loop_length = 0;
- Location* loc = 0;
+ Location* loc = loop_location;
+ framepos_t effective_start = start;
+ Evoral::Range<framepos_t>* loop_range (0);
MidiTrack* mt = dynamic_cast<MidiTrack*>(_track);
MidiChannelFilter* filter = mt ? &mt->playback_filter() : NULL;
- if (!reversed) {
-
- loc = loop_location;
- get_location_times(loc, &loop_start, &loop_end, &loop_length);
+ frameoffset_t loop_offset = 0;
- /* if we are looping, ensure that the first frame we read is at the correct
- position within the loop.
- */
-
- if (loc && (start >= loop_end)) {
- //cerr << "start adjusted from " << start;
- start = loop_start + ((start - loop_start) % loop_length);
- //cerr << "to " << start << endl;
- }
- // cerr << "start is " << start << " end " << start+dur << " loopstart: " << loop_start << " loopend: " << loop_end << endl;
+ if (!reversed && loc) {
+ get_location_times (loc, &loop_start, &loop_end, &loop_length);
}
while (dur) {
/* take any loop into account. we can't read past the end of the loop. */
- if (loc && (loop_end - start <= dur)) {
- this_read = loop_end - start;
- // cerr << "reloop true: thisread: " << this_read << " dur: " << dur << endl;
- reloop = true;
+ if (loc && !reversed) {
+
+ if (!loop_range) {
+ loop_range = new Evoral::Range<framepos_t> (loop_start, loop_end-1); // inclusive semantics require -1
+ }
+
+ /* if we are (seamlessly) looping, ensure that the first frame we read is at the correct
+ position within the loop.
+ */
+
+ effective_start = loop_range->squish (effective_start);
+
+ if ((loop_end - effective_start) <= dur) {
+ /* too close to end of loop to read "dur", so
+ shorten it.
+ */
+ this_read = loop_end - effective_start;
+ } else {
+ this_read = dur;
+ }
+
} else {
- reloop = false;
this_read = dur;
}
break;
}
- this_read = min(dur,this_read);
+ this_read = min (dur,this_read);
+
+ DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MDS ::read at %1 for %2 loffset %3\n", effective_start, this_read, loop_offset));
- if (midi_playlist()->read (*_playback_buf, start, this_read, 0, filter) != this_read) {
+ if (midi_playlist()->read (*_playback_buf, effective_start, this_read, loop_range, 0, filter) != this_read) {
error << string_compose(
_("MidiDiskstream %1: cannot read %2 from playlist at frame %3"),
id(), this_read, start) << endmsg;
} else {
- /* if we read to the end of the loop, go back to the beginning */
- if (reloop) {
- // Synthesize LoopEvent here, because the next events
- // written will have non-monotonic timestamps.
- start = loop_start;
- } else {
- start += this_read;
- }
+ /* adjust passed-by-reference argument (note: this is
+ monotonic and does not reflect looping.
+ */
+ start += this_read;
+
+ /* similarly adjust effective_start, but this may be
+ readjusted for seamless looping as we continue around
+ the loop.
+ */
+ effective_start += this_read;
}
dur -= this_read;
size_t write_space = _playback_buf->write_space();
bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
+ DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MDS refill, write space = %1 file frame = %2\n",
+ write_space, file_frame));
+
+ /* no space to write */
if (write_space == 0) {
return 0;
}
return 0;
}
- /* no space to write */
- if (_playback_buf->write_space() == 0) {
- return 0;
- }
-
uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
+
if ((frames_read < frames_written) && (frames_written - frames_read) >= midi_readahead) {
return 0;
}
framecnt_t to_read = midi_readahead - ((framecnt_t)frames_written - (framecnt_t)frames_read);
- //cout << "MDS read for midi_readahead " << to_read << " rb_contains: "
- // << frames_written - frames_read << endl;
-
to_read = min (to_read, (framecnt_t) (max_framepos - file_frame));
to_read = min (to_read, (framecnt_t) write_space);
_write_source->drop_references ();
_write_source.reset();
}
- }
+ }
}
Location* loc = loop_location;
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
- "%1 MDS pre-read read %8 @ %4..%5 from %2 write to %3, LOOPED ? %6-%7\n", _name,
+ "%1 MDS pre-read read %8 offset = %9 @ %4..%5 from %2 write to %3, LOOPED ? %6 .. %7\n", _name,
_playback_buf->get_read_ptr(), _playback_buf->get_write_ptr(), playback_sample, playback_sample + nframes,
- (loc ? loc->start() : -1), (loc ? loc->end() : -1), nframes));
+ (loc ? loc->start() : -1), (loc ? loc->end() : -1), nframes, Port::port_offset()));
- // cerr << "================\n";
- // _playback_buf->dump (cerr);
- // cerr << "----------------\n";
+ //cerr << "======== PRE ========\n";
+ //_playback_buf->dump (cerr);
+ //cerr << "----------------\n";
size_t events_read = 0;
- const size_t split_cycle_offset = Port::port_offset ();
if (loc) {
framepos_t effective_start;
- if (playback_sample >= loc->end()) {
- effective_start = loc->start() + ((playback_sample - loc->end()) % loc->length());
- } else {
- effective_start = playback_sample;
- }
+ Evoral::Range<framepos_t> loop_range (loc->start(), loc->end() - 1);
+ effective_start = loop_range.squish (playback_sample);
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("looped, effective start adjusted to %1\n", effective_start));
beyond the loop end.
*/
- _playback_buf->resolve_tracker (dst, split_cycle_offset);
+ _playback_buf->resolve_tracker (dst, 0);
}
- _playback_buf->skip_to (effective_start);
-
/* for split-cycles we need to offset the events */
if (loc->end() >= effective_start && loc->end() < effective_start + nframes) {
+
/* end of loop is within the range we are reading, so
split the read in two, and lie about the location
for the 2nd read
*/
+
framecnt_t first, second;
first = loc->end() - effective_start;
second = nframes - first;
- DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read for eff %1 end %2: %3 and %4\n",
- effective_start, loc->end(), first, second));
+ DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read for eff %1 end %2: %3 and %4, cycle offset %5\n",
+ effective_start, loc->end(), first, second));
if (first) {
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #1, from %1 for %2\n",
effective_start, first));
- events_read = _playback_buf->read (dst, effective_start, first, split_cycle_offset);
+ events_read = _playback_buf->read (dst, effective_start, first);
}
if (second) {
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #2, from %1 for %2\n",
loc->start(), second));
- events_read += _playback_buf->read (dst, loc->start(), second, split_cycle_offset);
+ events_read += _playback_buf->read (dst, loc->start(), second);
}
} else {
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #3, adjusted start as %1 for %2\n",
effective_start, nframes));
- events_read = _playback_buf->read (dst, effective_start, effective_start + nframes, split_cycle_offset);
+ events_read = _playback_buf->read (dst, effective_start, effective_start + nframes);
}
} else {
_playback_buf->skip_to (playback_sample);
- events_read = _playback_buf->read (dst, playback_sample, playback_sample + nframes, split_cycle_offset);
+ DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("playback buffer read, from %1 to %2 (%3)", playback_sample, playback_sample + nframes, nframes));
+ events_read = _playback_buf->read (dst, playback_sample, playback_sample + nframes);
}
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
_playback_buf->get_read_ptr(), _playback_buf->get_write_ptr()));
g_atomic_int_add (&_frames_read_from_ringbuffer, nframes);
+
+ //cerr << "======== POST ========\n";
+ //_playback_buf->dump (cerr);
+ //cerr << "----------------\n";
}
bool