fix construction of new xfades from legacy xfades, and add a few comments here and...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 1 Jun 2012 01:07:00 +0000 (01:07 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 1 Jun 2012 01:07:00 +0000 (01:07 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12519 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/audioplaylist.h
libs/ardour/audio_playlist.cc
libs/ardour/audioregion.cc

index 39efd2505d4a6d9b4fe424b68e7939b10e1c1d6d..a5f6b4ef390c465517fed09d09feef4a9a4dbb4c 100644 (file)
@@ -59,7 +59,8 @@ private:
        int set_state (const XMLNode&, int version);
        void dump () const;
        bool region_changed (const PBD::PropertyChange&, boost::shared_ptr<Region>);
-       void source_offset_changed (boost::shared_ptr<AudioRegion> region);
+       void source_offset_changed (boost::shared_ptr<AudioRegion>);
+        void load_legacy_crossfades (const XMLNode&, int version);
 };
 
 } /* namespace ARDOUR */
index 0054b6a1777c5430ce43f5b8fcc4d41d6fef4ef0..dad62daf4178c99092dbeb854bee311e703a06ea 100644 (file)
@@ -49,6 +49,8 @@ AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden
        in_set_state--;
 
        relayer ();
+
+       load_legacy_crossfades (node, Stateful::loading_state_version);
 }
 
 AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
@@ -200,7 +202,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
 
        /* This will be a list of the bits of regions that we need to read */
        list<Segment> to_do;
-       
+
        /* Now go through the `all' list filling in `to_do' and `done' */
        for (RegionList::iterator i = all->begin(); i != all->end(); ++i) {
                boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*i);
@@ -213,6 +215,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
                region_range.to = min (region_range.to, start + cnt - 1);
 
                /* ... and then remove the bits that are already done */
+
                Evoral::RangeList<framepos_t> region_to_do = Evoral::subtract (region_range, done);
 
                /* Read those bits, adding their bodies (the parts between end-of-fade-in
@@ -239,6 +242,10 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
 
        /* Now go backwards through the to_do list doing the actual reads */
        for (list<Segment>::reverse_iterator i = to_do.rbegin(); i != to_do.rend(); ++i) {
+               DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("\tPlaylist %1 read %2 @ %3 for %4, channel %5, buf @ %6 offset %7\n",
+                                                                  name(), i->region->name(), i->range.from,
+                                                                  i->range.to - i->range.from + 1, (int) chan_n,
+                                                                  buf, i->range.from - start));
                i->region->read_at (buf + i->range.from - start, mixdown_buffer, gain_buffer, i->range.from, i->range.to - i->range.from + 1, chan_n);
        }
 
@@ -656,11 +663,12 @@ AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boo
 int
 AudioPlaylist::set_state (const XMLNode& node, int version)
 {
-       int const r = Playlist::set_state (node, version);
-       if (r) {
-               return r;
-       }
+       return Playlist::set_state (node, version);
+}
 
+void
+AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
+{
        /* Read legacy Crossfade nodes and set up region fades accordingly */
 
        XMLNodeList children = node.children ();
@@ -689,28 +697,77 @@ AudioPlaylist::set_state (const XMLNode& node, int version)
 
                        boost::shared_ptr<AudioRegion> in_a = boost::dynamic_pointer_cast<AudioRegion> (in);
                        assert (in_a);
-                       
-                       const XMLNodeList c = (*i)->children ();
 
-                       for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
-                               if ((*j)->name() == X_("FadeIn")) {
-                                       in_a->fade_in()->set_state (**j, version);
-                               } else if ((*j)->name() == X_("FadeOut")) {
-                                       in_a->inverse_fade_in()->set_state (**j, version);
-                               }
+                       if ((p = (*i)->property (X_("out"))) == 0) {
+                               continue;
                        }
 
-                       if ((p = (*i)->property ("follow-overlap")) != 0) {
-                               in_a->set_fade_in_is_short (!string_is_affirmative (p->value()));
-                       } else {
-                               in_a->set_fade_in_is_short (false);
+                       boost::shared_ptr<Region> out = region_by_id (PBD::ID (p->value ()));
+
+                       if (!out) {
+                               warning << string_compose (_("Legacy crossfade involved an outgoing region not present in playlist \"%1\" - crossfade discarded"),
+                                                          name()) 
+                                       << endmsg;
+                               continue;
                        }
 
-                       in_a->set_fade_in_is_xfade (true);
-                       in_a->set_fade_in_active (true);
-                       cerr << in_a->name() << " from playlist fade in  = xfade false\n";
+                       boost::shared_ptr<AudioRegion> out_a = boost::dynamic_pointer_cast<AudioRegion> (out);
+                       assert (out_a);
+
+                       /* now decide whether to add a fade in or fade out
+                        * xfade and to which region
+                        */
+
+                       if (in->layer() <= out->layer()) {
+
+                               /* incoming region is below the outgoing one,
+                                * so apply a fade out to the outgoing one 
+                                */
+
+                               const XMLNodeList c = (*i)->children ();
+                               
+                               for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
+                                       if ((*j)->name() == X_("FadeOut")) {
+                                               out_a->fade_out()->set_state (**j, version);
+                                       } else if ((*j)->name() == X_("FadeIn")) {
+                                               out_a->inverse_fade_out()->set_state (**j, version);
+                                       }
+                               }
+                               
+                               if ((p = (*i)->property ("follow-overlap")) != 0) {
+                                       out_a->set_fade_out_is_short (!string_is_affirmative (p->value()));
+                               } else {
+                                       out_a->set_fade_out_is_short (false);
+                               }
+                               
+                               out_a->set_fade_out_is_xfade (true);
+                               out_a->set_fade_out_active (true);
+
+                       } else {
+
+                               /* apply a fade in to the incoming region,
+                                * since its above the outgoing one
+                                */
+
+                               const XMLNodeList c = (*i)->children ();
+                               
+                               for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
+                                       if ((*j)->name() == X_("FadeIn")) {
+                                               in_a->fade_in()->set_state (**j, version);
+                                       } else if ((*j)->name() == X_("FadeOut")) {
+                                               in_a->inverse_fade_in()->set_state (**j, version);
+                                       }
+                               }
+                               
+                               if ((p = (*i)->property ("follow-overlap")) != 0) {
+                                       in_a->set_fade_in_is_short (!string_is_affirmative (p->value()));
+                               } else {
+                                       in_a->set_fade_in_is_short (false);
+                               }
+                               
+                               in_a->set_fade_in_is_xfade (true);
+                               in_a->set_fade_in_active (true);
+                       }
                }
        }
-
-       return 0;
 }
index 248da959367a24ddbecf7bdde47429e0a29203c6..42a29c12af5dffe62921bf8590dd373e874ef941 100644 (file)
@@ -524,7 +524,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
 
        /* COMPUTE DETAILS OF ANY FADES INVOLVED IN THIS READ */
 
-       /* Amount of fade in that we are dealing with in this read */
+       /* Amount (length) of fade in that we are dealing with in this read */
        framecnt_t fade_in_limit = 0;
 
        /* Offset from buf / mixdown_buffer of the start
@@ -532,7 +532,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
        */
        frameoffset_t fade_out_offset = 0;
        
-       /* Amount of fade in that we are dealing with in this read */
+       /* Amount (length) of fade out that we are dealing with in this read */
        framecnt_t fade_out_limit = 0;
 
        framecnt_t fade_interval_start = 0;
@@ -542,7 +542,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
        if (_fade_in_active && _session.config.get_use_region_fades()) {
                
                framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
-               
+
                /* see if this read is within the fade in */
                
                if (internal_offset < fade_in_length) {
@@ -611,7 +611,6 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
                apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
        }
 
-
        /* APPLY FADES TO THE DATA IN mixdown_buffer AND MIX THE RESULTS INTO
         * buf. The key things to realize here: (1) the fade being applied is
         * (as of April 26th 2012) just the inverse of the fade in curve (2) 
@@ -623,6 +622,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
 
                if (opaque()) {
                        if (_inverse_fade_in) {
+
                                
                                /* explicit inverse fade in curve (e.g. for constant
                                 * power), so we have to fetch it.
@@ -671,7 +671,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
                                
                                _inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
                                
-                               /* Fade the data from lower levels out */
+                               /* Fade the data from lower levels in */
                                for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
                                        buf[m] *= gain_buffer[n];
                                }
@@ -682,7 +682,8 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
                                
                        } else {
                                
-                               /* no explicit inverse fade out, so just use (1 - fade
+                               /* no explicit inverse fade out (which is
+                                * actually a fade in), so just use (1 - fade
                                 * out) for the fade in of lower layers
                                 */
                                
@@ -696,12 +697,13 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
                        _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
                }
 
-               /* Mix our newly-read data out, with the fade */
+               /* Mix our newly-read data with whatever was already there,
+                  with the fade out applied to our data.
+               */
                for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
                        buf[m] += mixdown_buffer[m] * gain_buffer[n];
                }
        }
-
        
        /* MIX OR COPY THE REGION BODY FROM mixdown_buffer INTO buf */