X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudio_playlist.cc;h=b008e4ff980793073435cf8e992ceb002e5b342f;hb=6c6eef276d5dadfbe03479aa396554f888404627;hp=9b433d160bcfdb787faedc3ca4895e8f5d47d9d8;hpb=a98fa4bc61e26cd94aeb6720325633c4e6618155;p=ardour.git diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 9b433d160b..b008e4ff98 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -23,12 +23,10 @@ #include "ardour/types.h" #include "ardour/debug.h" -#include "ardour/configuration.h" #include "ardour/audioplaylist.h" #include "ardour/audioregion.h" #include "ardour/region_sorters.h" #include "ardour/session.h" -#include "pbd/enumwriter.h" #include "i18n.h" @@ -51,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) @@ -66,7 +66,7 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr other, stri AudioPlaylist::AudioPlaylist (boost::shared_ptr other, framepos_t start, framecnt_t cnt, string name, bool hidden) : Playlist (other, start, cnt, name, hidden) { - RegionLock rlock2 (const_cast (other.get())); + RegionReadLock rlock2 (const_cast (other.get())); in_set_state++; framepos_t const end = start + cnt - 1; @@ -186,7 +186,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr its OK to block (for short intervals). */ - Playlist::RegionLock rl (this, false); + Playlist::RegionReadLock rl (this); /* Find all the regions that are involved in the bit we are reading, and sort them by descending layer and ascending position. @@ -202,11 +202,15 @@ 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 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 ar = boost::dynamic_pointer_cast (*i); + /* muted regions don't figure into it at all */ + if ( ar->muted() ) + continue; + /* Work out which bits of this region need to be read; first, trim to the range we are reading... */ @@ -215,9 +219,10 @@ 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 region_to_do = Evoral::subtract (region_range, done); - /* Read those bits, adding their bodies (the parts between end-of-fade-in + /* Make a note to read those bits, adding their bodies (the parts between end-of-fade-in and start-of-fade-out) to the `done' list. */ @@ -241,169 +246,16 @@ 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::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); } return cnt; } -void -AudioPlaylist::check_crossfades (Evoral::Range range) -{ - if (in_set_state || in_partition || !_session.config.get_auto_xfade ()) { - return; - } - - boost::shared_ptr starts = regions_with_start_within (range); - boost::shared_ptr ends = regions_with_end_within (range); - - RegionList all = *starts; - std::copy (ends->begin(), ends->end(), back_inserter (all)); - - all.sort (RegionSortByLayer ()); - - set > done_start; - set > done_end; - - for (RegionList::reverse_iterator i = all.rbegin(); i != all.rend(); ++i) { - for (RegionList::reverse_iterator j = all.rbegin(); j != all.rend(); ++j) { - - if (i == j) { - continue; - } - - if ((*i)->muted() || (*j)->muted()) { - continue; - } - - if ((*i)->position() == (*j)->position() && ((*i)->length() == (*j)->length())) { - /* precise overlay: no xfade */ - continue; - } - - if ((*i)->position() == (*j)->position() || ((*i)->last_frame() == (*j)->last_frame())) { - /* starts or ends match: no xfade */ - continue; - } - - boost::shared_ptr top; - boost::shared_ptr bottom; - - if ((*i)->layer() < (*j)->layer()) { - top = boost::dynamic_pointer_cast (*j); - bottom = boost::dynamic_pointer_cast (*i); - } else { - top = boost::dynamic_pointer_cast (*i); - bottom = boost::dynamic_pointer_cast (*j); - } - - if (!top->opaque ()) { - continue; - } - - Evoral::OverlapType const c = top->coverage (bottom->position(), bottom->last_frame()); - - if (c == Evoral::OverlapStart) { - - /* top starts within bottom but covers bottom's end */ - - /* { ==== top ============ } - * [---- bottom -------------------] - */ - - if (done_start.find (top) == done_start.end() && done_end.find (bottom) == done_end.end ()) { - - /* Top's fade-in will cause an implicit fade-out of bottom */ - - framecnt_t len = 0; - switch (_session.config.get_xfade_model()) { - case FullCrossfade: - len = bottom->last_frame () - top->first_frame (); - break; - case ShortCrossfade: - len = _session.config.get_short_xfade_seconds() * _session.frame_rate(); - break; - } - - top->set_fade_in_active (true); - top->set_fade_in_is_xfade (true); - - /* XXX may 2012: -3dB and -6dB curves - * are the same right now - */ - - switch (_session.config.get_xfade_choice ()) { - case ConstantPowerMinus3dB: - top->set_fade_in (FadeConstantPower, len); - break; - case ConstantPowerMinus6dB: - top->set_fade_in (FadeConstantPower, len); - break; - case RegionFades: - top->set_fade_in_length (len); - break; - } - - done_start.insert (top); - } - - } else if (c == Evoral::OverlapEnd) { - - /* top covers start of bottom but ends within it */ - - /* [---- top ------------------------] - * { ==== bottom ============ } - */ - - if (done_end.find (top) == done_end.end() && done_start.find (bottom) == done_start.end ()) { - /* Top's fade-out will cause an implicit fade-in of bottom */ - - framecnt_t len = 0; - switch (_session.config.get_xfade_model()) { - case FullCrossfade: - len = top->last_frame () - bottom->first_frame (); - break; - case ShortCrossfade: - len = _session.config.get_short_xfade_seconds() * _session.frame_rate(); - break; - } - - top->set_fade_out_active (true); - top->set_fade_out_is_xfade (true); - - switch (_session.config.get_xfade_choice ()) { - case ConstantPowerMinus3dB: - top->set_fade_out (FadeConstantPower, len); - break; - case ConstantPowerMinus6dB: - top->set_fade_out (FadeConstantPower, len); - break; - case RegionFades: - top->set_fade_out_length (len); - break; - } - - done_end.insert (top); - } - } - } - } - - for (RegionList::iterator i = starts->begin(); i != starts->end(); ++i) { - if (done_start.find (*i) == done_start.end()) { - boost::shared_ptr r = boost::dynamic_pointer_cast (*i); - r->set_default_fade_in (); - } - } - - for (RegionList::iterator i = ends->begin(); i != ends->end(); ++i) { - if (done_end.find (*i) == done_end.end()) { - boost::shared_ptr r = boost::dynamic_pointer_cast (*i); - r->set_default_fade_out (); - } - } -} - void AudioPlaylist::dump () const { @@ -437,7 +289,7 @@ AudioPlaylist::destroy_region (boost::shared_ptr region) bool changed = false; { - RegionLock rlock (this); + RegionWriteLock rlock (this); for (RegionList::iterator i = regions.begin(); i != regions.end(); ) { @@ -623,11 +475,12 @@ AudioPlaylist::pre_uncombine (vector >& 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 (); @@ -636,36 +489,83 @@ AudioPlaylist::set_state (const XMLNode& node, int version) XMLProperty* p = (*i)->property (X_("active")); assert (p); + if (!string_is_affirmative (p->value())) { continue; } + + if ((p = (*i)->property (X_("in"))) == 0) { + continue; + } - p = (*i)->property (X_("in")); - assert (p); boost::shared_ptr in = region_by_id (PBD::ID (p->value ())); - assert (in); + + if (!in) { + warning << string_compose (_("Legacy crossfade involved an incoming region not present in playlist \"%1\" - crossfade discarded"), + name()) + << endmsg; + continue; + } + boost::shared_ptr in_a = boost::dynamic_pointer_cast (in); assert (in_a); - p = (*i)->property (X_("out")); - assert (p); + if ((p = (*i)->property (X_("out"))) == 0) { + continue; + } + boost::shared_ptr out = region_by_id (PBD::ID (p->value ())); - assert (out); + + if (!out) { + warning << string_compose (_("Legacy crossfade involved an outgoing region not present in playlist \"%1\" - crossfade discarded"), + name()) + << endmsg; + continue; + } + boost::shared_ptr out_a = boost::dynamic_pointer_cast (out); assert (out_a); - 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); - in_a->set_fade_in_active (true); - } else if ((*j)->name() == X_("FadeOut")) { - out_a->fade_out()->set_state (**j, version); - out_a->set_fade_out_active (true); + /* 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); + } + } + + 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); + } } + + in_a->set_fade_in_active (true); } } } - - return 0; }