centralize determination of "read-audio-data-in-reverse" and fix seek "shift" offset

There is still a bug related to "shift" that causes a playback discontinuity
This commit is contained in:
Paul Davis 2020-02-21 11:53:53 -07:00
parent f0316430c6
commit 8e8d2f86a8
5 changed files with 64 additions and 39 deletions

View File

@ -67,23 +67,17 @@ public:
void move_processor_automation (boost::weak_ptr<Processor>, std::list<Evoral::RangeMove<samplepos_t> > const &);
/* called by the Butler in a non-realtime context as part of its
* normal loop (not due to transport-mechanism requests like locate
/* called by the Butler in a non-realtime context as part of its normal
* buffer refill loop (not due to transport-mechanism requests like
* locate)
*/
int do_refill () {
return refill (_sum_buffer, _mixdown_buffer, _gain_buffer, 0);
}
int do_refill ();
/** For contexts outside the normal butler refill loop (allocates temporary working buffers)
*
* This accessible method has a default argument; derived classes
* must inherit the virtual method that we call which does NOT
* have a default argument, to avoid complications with inheritance
*/
int do_refill_with_alloc (bool partial_fill = true) {
return _do_refill_with_alloc (partial_fill);
}
int do_refill_with_alloc (bool partial_fill, bool reverse);
bool pending_overwrite () const;
@ -195,9 +189,7 @@ private:
DeclickAmp _declick_amp;
sampleoffset_t _declick_offs;
MidiStateTracker _tracker;
boost::optional<bool> _last_read_reversed;
int _do_refill_with_alloc (bool partial_fill);
boost::optional<bool> _last_read_reversed;
static samplecnt_t _chunk_samples;
static gint _no_disk_output;
@ -218,8 +210,8 @@ private:
static Sample* _mixdown_buffer;
static gain_t* _gain_buffer;
int refill (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, samplecnt_t fill_level);
int refill_audio (Sample* sum_buffer, Sample *mixdown_buffer, float *gain_buffer, samplecnt_t fill_level);
int refill (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, samplecnt_t fill_level, bool reversed);
int refill_audio (Sample* sum_buffer, Sample *mixdown_buffer, float *gain_buffer, samplecnt_t fill_level, bool reversed);
sampleoffset_t calculate_playback_distance (pframes_t);

View File

@ -299,7 +299,7 @@ AudioTrackImporter::_move ()
boost::shared_ptr<DiskReader> new_ds (new DiskReader (session, *ds_node));
new_ds->set_name (name);
new_ds->do_refill_with_alloc ();
new_ds->do_refill_with_alloc (true, false);
new_ds->set_block_size (session.get_block_size ());
/* Import playlists */

View File

@ -774,6 +774,7 @@ DiskReader::seek (samplepos_t sample, bool complete_refill)
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
(*chan)->rbuf->reset ();
assert ((*chan)->rbuf->reserved_size() == 0);
}
/* move the intended read target, so that after the refill is done,
@ -783,7 +784,18 @@ DiskReader::seek (samplepos_t sample, bool complete_refill)
samples.
*/
const samplecnt_t shift = sample > c->front()->rbuf->reservation_size() ? c->front()->rbuf->reservation_size() : sample;
samplecnt_t shift = sample > c->front()->rbuf->reservation_size() ? c->front()->rbuf->reservation_size() : sample;
// shift = 0;
if (read_reversed) {
/* reading in reverse, so start at a later sample, and read
"backwards" from there.
*/
shift = -shift;
}
/* start the read at an earlier position (or later if reversed) */
sample -= shift;
@ -795,22 +807,37 @@ DiskReader::seek (samplepos_t sample, bool complete_refill)
/* call _do_refill() to refill the entire buffer, using
the largest reads possible.
*/
while ((ret = do_refill_with_alloc (false)) > 0) ;
while ((ret = do_refill_with_alloc (false, read_reversed)) > 0) ;
} else {
/* call _do_refill() to refill just one chunk, and then
return.
*/
ret = do_refill_with_alloc (true);
ret = do_refill_with_alloc (true, read_reversed);
}
sample += shift;
if (shift) {
playback_sample = sample;
file_sample[DataType::AUDIO] = sample;
file_sample[DataType::MIDI] = sample;
/* now tell everyone where we really are, leaving the
* "reserved" data represented by "shift" available in the
* buffer for backwards-internal-seek
*/
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
(*chan)->rbuf->increment_read_ptr (shift);
sample += shift;
playback_sample = sample;
file_sample[DataType::AUDIO] = sample;
file_sample[DataType::MIDI] = sample;
/* we always move the read-ptr forwards, since even when in
* reverse, the data is placed in the buffer in normal read
* (increment) order.
*/
shift = abs (shift);
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
(*chan)->rbuf->increment_read_ptr (shift);
}
}
return ret;
@ -1001,7 +1028,14 @@ DiskReader::audio_read (Sample* sum_buffer,
}
int
DiskReader::_do_refill_with_alloc (bool partial_fill)
DiskReader::do_refill ()
{
const bool reversed = !_session.transport_will_roll_forwards ();
return refill (_sum_buffer, _mixdown_buffer, _gain_buffer, 0, reversed);
}
int
DiskReader::do_refill_with_alloc (bool partial_fill, bool reversed)
{
/* We limit disk reads to at most 4MB chunks, which with floating point
samples would be 1M samples. But we might use 16 or 14 bit samples,
@ -1013,21 +1047,21 @@ DiskReader::_do_refill_with_alloc (bool partial_fill)
boost::scoped_array<Sample> mix_buf (new Sample[2*1048576]);
boost::scoped_array<float> gain_buf (new float[2*1048576]);
return refill_audio (sum_buf.get(), mix_buf.get(), gain_buf.get(), (partial_fill ? _chunk_samples : 0));
return refill_audio (sum_buf.get(), mix_buf.get(), gain_buf.get(), (partial_fill ? _chunk_samples : 0), reversed);
}
int
DiskReader::refill (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, samplecnt_t fill_level)
DiskReader::refill (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, samplecnt_t fill_level, bool reversed)
{
/* NOTE: Audio refill MUST come first so that in contexts where ONLY it
is called, _last_read_reversed is set correctly.
*/
if (refill_audio (sum_buffer, mixdown_buffer, gain_buffer, fill_level)) {
if (refill_audio (sum_buffer, mixdown_buffer, gain_buffer, fill_level, reversed)) {
return -1;
}
if (rt_midibuffer() && (_session.transport_speed() < 0.0f) != rt_midibuffer()->reversed()) {
if (rt_midibuffer() && (reversed != rt_midibuffer()->reversed())) {
rt_midibuffer()->reverse ();
}
@ -1045,7 +1079,7 @@ DiskReader::refill (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buff
*/
int
DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, samplecnt_t fill_level)
DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, samplecnt_t fill_level, bool reversed)
{
/* do not read from disk while session is marked as Loading, to avoid
useless redundant I/O.
@ -1056,13 +1090,12 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai
}
int32_t ret = 0;
bool const reversed = !_session.transport_will_roll_forwards ();
samplecnt_t zero_fill;
uint32_t chan_n;
ChannelList::iterator i;
boost::shared_ptr<ChannelList> c = channels.reader();
_last_read_reversed = !_session.transport_will_roll_forwards ();
_last_read_reversed = reversed;
if (c->empty()) {
return 0;

View File

@ -481,7 +481,7 @@ Session::process_with_events (pframes_t nframes)
assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
samples_moved = (samplecnt_t) nframes * _transport_speed;
DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
// DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
end_sample = _transport_sample + samples_moved;
@ -642,12 +642,12 @@ Session::process_without_events (pframes_t nframes)
assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
if (_transport_speed == 0) {
DEBUG_TRACE (DEBUG::Transport, string_compose ("transport not moving @ %1\n", _transport_sample));
// DEBUG_TRACE (DEBUG::Transport, string_compose ("transport not moving @ %1\n", _transport_sample));
no_roll (nframes);
return;
} else {
samples_moved = (samplecnt_t) nframes * _transport_speed;
DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
// DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
}
if (!_exporting && !timecode_transmission_suspended()) {

View File

@ -29,7 +29,7 @@
using namespace ARDOUR;
using namespace PBD;
const uint32_t SrcFileSource::max_blocksize = 2097152U; /* see AudioDiskstream::_do_refill_with_alloc, max */
const uint32_t SrcFileSource::max_blocksize = 2097152U; /* see AudioDiskstream::do_refill_with_alloc, max */
SrcFileSource::SrcFileSource (Session& s, boost::shared_ptr<AudioFileSource> src, SrcQuality srcq)
: Source(s, DataType::AUDIO, src->name(), Flag (src->flags() & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))