diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 07a6e99dec..317363182d 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -289,6 +289,7 @@ class LIBARDOUR_API AudioRegion : public Region, public AudioReadable int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal); void send_change (const PBD::PropertyChange&); + void ensure_length_sanity (); }; } /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index df7b83484a..5d3c9fe39f 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -573,6 +573,7 @@ protected: virtual void set_start_internal (timepos_t const &); bool verify_start_and_length (timepos_t const &, timecnt_t&); void first_edit (); + virtual void ensure_length_sanity () {} void override_opaqueness (bool yn) { _opaque = yn; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 4a7e74432e..e90dee6688 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -438,6 +438,8 @@ AudioRegion::~AudioRegion () void AudioRegion::post_set (const PropertyChange& /*ignored*/) { + ensure_length_sanity (); + if (!_sync_marked) { _sync_position = _start; } @@ -2701,3 +2703,19 @@ AudioRegion::apply_region_fx (BufferSet& bufs, samplepos_t start_sample, samplep _fx_pos = end_sample; _fx_latent_read = false; } + +void +AudioRegion::ensure_length_sanity () +{ + if (_type == DataType::AUDIO) { + /* Force audio regions to have a length that is the + rounded-down integer number of samples. No other value makes + any sort of logical sense. We tried to fix this at a lower + level, by rounding the return value of + TempoMap::superclock_at(), but the breaks the fundamental + point of a high resolution audio time unit. + */ + _length = timecnt_t (timepos_t (_length.val().samples()), _length.val().position()); + } +} + diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 9d6fea03cb..dd2c179d91 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -304,6 +304,7 @@ Region::Region (Session& s, timepos_t const & start, timecnt_t const & length, c , _changemap (0) { register_properties (); + ensure_length_sanity (); /* no sources at this point */ } @@ -324,6 +325,7 @@ Region::Region (const SourceList& srcs) register_properties (); use_sources (srcs); + ensure_length_sanity (); assert(_sources.size() > 0); assert (_type == srcs.front()->type()); @@ -382,6 +384,7 @@ Region::Region (std::shared_ptr other) _sync_position = _start; } + ensure_length_sanity (); assert (_type == other->data_type()); } @@ -433,6 +436,7 @@ Region::Region (std::shared_ptr other, timecnt_t const & offset) _sync_position = _start; } + ensure_length_sanity (); assert (_type == other->data_type()); } @@ -462,6 +466,7 @@ Region::Region (std::shared_ptr other, const SourceList& srcs) } use_sources (srcs); + ensure_length_sanity (); assert(_sources.size() > 0); } @@ -567,25 +572,34 @@ Region::set_length_internal (timecnt_t const & len) _last_length = timecnt_t (_length.val().distance(), _last_length.position()); - std::shared_ptr pl (playlist()); + if (_type == DataType::AUDIO) { - if (pl) { - Temporal::TimeDomain td (pl->time_domain()); + /* Equivalent to what AudioRegion::ensure_length_sanity() does */ + _length = timecnt_t (timepos_t (len.samples()), _length.val().position()); - /* Note: timecnt_t::time_domain() returns the domain for the - * length component, *not* the position. - */ + } else { - if (td != len.time_domain()) { - timecnt_t l = _length.val(); - l.set_time_domain (td); - _length = l; - return; + std::shared_ptr pl (playlist()); + + if (pl) { + Temporal::TimeDomain td (pl->time_domain()); + + /* Note: timecnt_t::time_domain() returns the domain for the + * length component, *not* the position. + */ + + if (td != len.time_domain()) { + timecnt_t l = _length.val(); + l.set_time_domain (td); + _length = l; + return; + } } - } - /* either no playlist or time domain for distance is not changing */ - _length = timecnt_t (len.distance(), _length.val().position()); + /* either no playlist or time domain for distance is not changing */ + + _length = timecnt_t (len.distance(), _length.val().position()); + } } void