trim a single other region when adjusting xfade length
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 10 May 2012 18:17:47 +0000 (18:17 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 10 May 2012 18:17:47 +0000 (18:17 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12241 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/audioregion.h
libs/ardour/ardour/region.h
libs/ardour/audioregion.cc
libs/ardour/region.cc

index fd6c3a85288565f56a45758a6507f8c5004c32c4..013629637d4d9d07ebc3ad20c6491f203d2f895a 100644 (file)
@@ -238,6 +238,8 @@ class AudioRegion : public Region
        bool                              _fade_in_is_xfade;
        bool                              _fade_out_is_xfade;
 
+       boost::shared_ptr<ARDOUR::Region> get_single_other_xfade_region (bool start) const;
+
   protected:
        /* default constructor for derived (compound) types */
 
index 788a8d90c914e586175e503d9fc9fa258f7c2ab3..1d7894fac52e8c376d80b6e45ba7227e68c93b8f 100644 (file)
@@ -141,6 +141,15 @@ class Region
        framepos_t first_frame () const { return _position; }
        framepos_t last_frame ()  const { return _position + _length - 1; }
 
+       /** Return the earliest possible value of _position given the
+        *  value of _start within the region's sources
+        */
+       framepos_t earliest_possible_position () const;
+       /** Return the last possible value of _last_frame given the
+        *  value of _startin the regions's sources
+        */
+       framepos_t latest_possible_frame () const;
+
        Evoral::Range<framepos_t> last_range () const {
                return Evoral::Range<framepos_t> (_last_position, _last_position + _last_length - 1);
        }
index 4ba383b37e7ed8514723d8a0598853436654ca90..36d5cf0a8c4211d3af3c78c542ab3882225ccdf1 100644 (file)
@@ -1148,6 +1148,20 @@ AudioRegion::set_fade_in_length (framecnt_t len)
                if (_inverse_fade_in) {
                        _inverse_fade_in->extend_to (len);
                }
+
+               if (_fade_in_is_xfade) {
+
+                       /* trim a single other region below us to the new start
+                          of the fade.
+                       */
+
+                       boost::shared_ptr<Region> other = get_single_other_xfade_region (true);
+                       if (other) {
+                               other->trim_end (position() + len);
+                       }
+               }
+
+
                _default_fade_in = false;
                send_change (PropertyChange (Properties::fade_in));
        }
@@ -1167,10 +1181,24 @@ AudioRegion::set_fade_out_length (framecnt_t len)
        bool changed =  _fade_out->extend_to (len);
 
        if (changed) {
+               
                if (_inverse_fade_out) {
                        _inverse_fade_out->extend_to (len);
                }
                _default_fade_out = false;
+
+               if (_fade_out_is_xfade) {
+
+                       /* trim a single other region below us to the new start
+                          of the fade.
+                       */
+
+                       boost::shared_ptr<Region> other = get_single_other_xfade_region (false);
+                       if (other) {
+                               other->trim_front (last_frame() - len);
+                       }
+               }
+
                send_change (PropertyChange (Properties::fade_out));
        }
 }
@@ -1801,8 +1829,8 @@ AudioRegion::set_fade_out_is_xfade (bool yn)
        _fade_out_is_xfade = yn;
 }
 
-framecnt_t
-AudioRegion::verify_xfade_bounds (framecnt_t len, bool start)
+boost::shared_ptr<Region>
+AudioRegion::get_single_other_xfade_region (bool start) const
 {
        boost::shared_ptr<Playlist> pl (playlist());
 
@@ -1810,11 +1838,10 @@ AudioRegion::verify_xfade_bounds (framecnt_t len, bool start)
                /* not currently in a playlist - xfade length is unbounded
                   (and irrelevant)
                */
-               return len;
+               return boost::shared_ptr<AudioRegion> ();
        }
 
        boost::shared_ptr<RegionList> rl;
-       framecnt_t maxlen;
 
        if (start) {
                rl = pl->regions_at (position());
@@ -1837,17 +1864,27 @@ AudioRegion::verify_xfade_bounds (framecnt_t len, bool start)
 
        if (n != 2) {
                /* zero or multiple regions stacked here - don't care about xfades */
-               return len;
+               return boost::shared_ptr<AudioRegion> ();
        }
 
+       return other;
+}
+
+framecnt_t
+AudioRegion::verify_xfade_bounds (framecnt_t len, bool start)
+{
+       boost::shared_ptr<Region> other = get_single_other_xfade_region (start);
+       framecnt_t maxlen;
+
        /* we overlap a single region. clamp the length of an xfade to
-          the duration of the overlap.
+          the maximum possible duration of the overlap (if the other
+          region were trimmed appropriately).
        */
 
        if (start) {
-               maxlen = other->last_frame() - position();
+               maxlen = other->latest_possible_frame() - position();
        } else {
-               maxlen = last_frame() - other->position();
+               maxlen = last_frame() - other->earliest_possible_position();
        }
 
        return min (maxlen, len);
index efaa104d351bef9f33f4281163e769395b2a8552..a4a158479278eb529955c3a3c68423d599b55aa9 100644 (file)
@@ -1654,3 +1654,33 @@ Region::set_start_internal (framecnt_t s)
 {
        _start = s;
 }
+
+framepos_t
+Region::earliest_possible_position () const
+{
+       if (_start > _position) {
+               return 0;
+       } else {
+               return _position - _start;
+       }
+}
+
+framecnt_t
+Region::latest_possible_frame () const
+{
+       framecnt_t minlen = max_framecnt;
+
+       for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
+               /* non-audio regions have a length that may vary based on their
+                * position, so we have to pass it in the call.
+                */
+               minlen = min (minlen, (*i)->length (_position));
+       }
+
+       /* the latest possible last frame is determined by the current
+        * position, plus the shortest source extent past _start.
+        */
+
+       return _position + (minlen - _start) - 1;
+}
+