diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2012-04-27 20:57:48 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2012-04-27 20:57:48 +0000 |
commit | f78913cc99ffd13001b4c4daf625391be77e79d0 (patch) | |
tree | 7576a54e9312d9c3bbfd490671c3b2b6702a5c51 | |
parent | d1af0b89a847fbde9a30a95e0198380ff6f4e68d (diff) |
Crossfades: default xfades are now constant-power, -3dB rule, other options are constant power(-6dB) rule or use existing region fade shape as is; provide GUI control over options; fix some inconsistent behaviour regarding xfades when relayering
git-svn-id: svn://localhost/ardour2/branches/3.0@12113 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/session_option_editor.cc | 13 | ||||
-rw-r--r-- | libs/ardour/ardour/audioregion.h | 10 | ||||
-rw-r--r-- | libs/ardour/ardour/playlist.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/session_configuration_vars.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 12 | ||||
-rw-r--r-- | libs/ardour/audio_playlist.cc | 40 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 86 | ||||
-rw-r--r-- | libs/ardour/enums.cc | 23 | ||||
-rw-r--r-- | libs/ardour/playlist.cc | 24 |
9 files changed, 177 insertions, 34 deletions
diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc index 62d555c13d..fe9e06c3a3 100644 --- a/gtk2_ardour/session_option_editor.cc +++ b/gtk2_ardour/session_option_editor.cc @@ -154,6 +154,19 @@ SessionOptionEditor::SessionOptionEditor (Session* s) add_option (_("Fades"), cfm); + ComboOption<CrossfadeChoice>* cfc = new ComboOption<CrossfadeChoice> ( + "xfade-choice", + _("Crossfade Type"), + sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfade_choice), + sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfade_choice) + ); + + cfc->add (ConstantPowerMinus3dB, _("Constant Power (-3dB)")); + cfc->add (ConstantPowerMinus6dB, _("Constant Power (-6dB)")); + cfc->add (RegionFades, _("Use existing Region fade shape")); + + add_option (_("Fades"), cfc); + add_option (_("Fades"), new SpinOption<float> ( _("short-xfade-seconds"), _("Short crossfade length"), diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 7236cd69a9..87d515d399 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -89,6 +89,11 @@ class AudioRegion : public Region bool fade_in_active () const { return _fade_in_active; } bool fade_out_active () const { return _fade_out_active; } + bool fade_in_is_xfade() const { return _fade_in_is_xfade; } + void set_fade_in_is_xfade (bool yn); + bool fade_out_is_xfade() const { return _fade_out_is_xfade; } + void set_fade_out_is_xfade (bool yn); + boost::shared_ptr<AutomationList> fade_in() { return _fade_in; } boost::shared_ptr<AutomationList> fade_out() { return _fade_out; } boost::shared_ptr<AutomationList> envelope() { return _envelope; } @@ -232,6 +237,11 @@ class AudioRegion : public Region boost::shared_ptr<AutomationList> _envelope; uint32_t _fade_in_suspended; uint32_t _fade_out_suspended; + /* This is not a Property because its not subject to user control, + or undo/redo. XXX this may prove to be a mistake. + */ + bool _fade_in_is_xfade; + bool _fade_out_is_xfade; protected: /* default constructor for derived (compound) types */ diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index d57df6999b..559a24062b 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -367,7 +367,7 @@ public: private: - void setup_layering_indices (RegionList const &) const; + void setup_layering_indices (RegionList const &); void coalesce_and_check_crossfades (std::list<Evoral::Range<framepos_t> >); boost::shared_ptr<RegionList> find_regions_at (framepos_t); }; diff --git a/libs/ardour/ardour/session_configuration_vars.h b/libs/ardour/ardour/session_configuration_vars.h index a6147f9140..16ce36020b 100644 --- a/libs/ardour/ardour/session_configuration_vars.h +++ b/libs/ardour/ardour/session_configuration_vars.h @@ -26,6 +26,7 @@ *****************************************************/ CONFIG_VARIABLE (CrossfadeModel, xfade_model, "xfade-model", FullCrossfade) +CONFIG_VARIABLE (CrossfadeChoice, xfade_choice, "xfade-choice", ConstantPowerMinus3dB) CONFIG_VARIABLE (bool, auto_xfade, "auto-xfade", true) CONFIG_VARIABLE (float, short_xfade_seconds, "short-xfade-seconds", 0.015) CONFIG_VARIABLE (bool, xfades_active, "xfades-active", true) diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index b3c1666dbb..71c00e7520 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -406,6 +406,12 @@ namespace ARDOUR { ShortCrossfade }; + enum CrossfadeChoice { + RegionFades, + ConstantPowerMinus3dB, + ConstantPowerMinus6dB, + }; + enum ListenPosition { AfterFaderListen, PreFaderListen @@ -558,7 +564,9 @@ namespace ARDOUR { FadeFast, FadeSlow, FadeLogA, - FadeLogB + FadeLogB, + FadeConstantPowerMinus3dB, + FadeConstantPowerMinus6dB, }; } // namespace ARDOUR @@ -579,6 +587,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::RemoteModel& sf); std::istream& operator>>(std::istream& o, ARDOUR::ListenPosition& sf); std::istream& operator>>(std::istream& o, ARDOUR::InsertMergePolicy& sf); std::istream& operator>>(std::istream& o, ARDOUR::CrossfadeModel& sf); +std::istream& operator>>(std::istream& o, ARDOUR::CrossfadeChoice& sf); std::istream& operator>>(std::istream& o, ARDOUR::SyncSource& sf); std::istream& operator>>(std::istream& o, ARDOUR::ShuttleBehaviour& sf); std::istream& operator>>(std::istream& o, ARDOUR::ShuttleUnits& sf); @@ -599,6 +608,7 @@ std::ostream& operator<<(std::ostream& o, const ARDOUR::RemoteModel& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::ListenPosition& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::InsertMergePolicy& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::CrossfadeModel& sf); +std::ostream& operator<<(std::ostream& o, const ARDOUR::CrossfadeChoice& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::SyncSource& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::ShuttleBehaviour& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::ShuttleUnits& sf); diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index ebebc62c33..f1c89cc565 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -290,7 +290,6 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range) continue; } - boost::shared_ptr<AudioRegion> top; boost::shared_ptr<AudioRegion> bottom; @@ -317,8 +316,9 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range) */ 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 */ + /* Top's fade-in will cause an implicit fade-out of bottom */ + framecnt_t len = 0; switch (_session.config.get_xfade_model()) { case FullCrossfade: @@ -328,11 +328,22 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range) len = _session.config.get_short_xfade_seconds() * _session.frame_rate(); break; } - - top->set_fade_in_length (len); + + switch (_session.config.get_xfade_choice ()) { + case ConstantPowerMinus3dB: + top->set_fade_in (FadeConstantPowerMinus3dB, len); + break; + case ConstantPowerMinus6dB: + top->set_fade_in (FadeConstantPowerMinus6dB, len); + break; + case RegionFades: + top->set_fade_in_length (len); + break; + } top->set_fade_in_active (true); + top->set_fade_in_is_xfade (true); + done_start.insert (top); - done_end.insert (bottom); } } else if (c == Evoral::OverlapEnd) { @@ -349,17 +360,28 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range) framecnt_t len = 0; switch (_session.config.get_xfade_model()) { case FullCrossfade: - len = bottom->last_frame () - top->first_frame (); + 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_length (len); + + switch (_session.config.get_xfade_choice ()) { + case ConstantPowerMinus3dB: + top->set_fade_out (FadeConstantPowerMinus3dB, len); + break; + case ConstantPowerMinus6dB: + top->set_fade_out (FadeConstantPowerMinus6dB, len); + break; + case RegionFades: + top->set_fade_out_length (len); + break; + } top->set_fade_out_active (true); + top->set_fade_out_is_xfade (true); + done_end.insert (top); - done_start.insert (bottom); } } } diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 8992f8ccca..79ee58b410 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -137,6 +137,8 @@ AudioRegion::AudioRegion (Session& s, framepos_t start, framecnt_t len, std::str , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation))) , _fade_in_suspended (0) , _fade_out_suspended (0) + , _fade_in_is_xfade (false) + , _fade_out_is_xfade (false) { init (); assert (_sources.size() == _master_sources.size()); @@ -152,6 +154,8 @@ AudioRegion::AudioRegion (const SourceList& srcs) , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation))) , _fade_in_suspended (0) , _fade_out_suspended (0) + , _fade_in_is_xfade (false) + , _fade_out_is_xfade (false) { init (); assert (_sources.size() == _master_sources.size()); @@ -169,6 +173,8 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other) , _envelope (new AutomationList (*other->_envelope, 0, other->_length)) , _fade_in_suspended (0) , _fade_out_suspended (0) + , _fade_in_is_xfade (false) + , _fade_out_is_xfade (false) { /* don't use init here, because we got fade in/out from the other region */ @@ -193,6 +199,8 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t , _envelope (new AutomationList (*other->_envelope, offset, other->_length)) , _fade_in_suspended (0) , _fade_out_suspended (0) + , _fade_in_is_xfade (false) + , _fade_out_is_xfade (false) { /* don't use init here, because we got fade in/out from the other region */ @@ -214,6 +222,8 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const Sour , _envelope (new AutomationList (*other->_envelope)) , _fade_in_suspended (0) , _fade_out_suspended (0) + , _fade_in_is_xfade (false) + , _fade_out_is_xfade (false) { /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */ @@ -235,6 +245,8 @@ AudioRegion::AudioRegion (SourceList& srcs) , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation))) , _fade_in_suspended (0) , _fade_out_suspended (0) + , _fade_in_is_xfade (false) + , _fade_out_is_xfade (false) { init (); @@ -818,6 +830,26 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len) _fade_in->fast_simple_add (len * 0.919355, 0.730556); _fade_in->fast_simple_add (len, 1); break; + + case FadeConstantPowerMinus3dB: + _fade_in->fast_simple_add (0.0, 0.0); + _fade_in->fast_simple_add ((len * 0.166667), 0.282192); + _fade_in->fast_simple_add ((len * 0.333333), 0.518174); + _fade_in->fast_simple_add ((len * 0.500000), 0.707946); + _fade_in->fast_simple_add ((len * 0.666667), 0.851507); + _fade_in->fast_simple_add ((len * 0.833333), 0.948859); + _fade_in->fast_simple_add (len, 1.0); + break; + + case FadeConstantPowerMinus6dB: + _fade_in->fast_simple_add (0.0, 0.0); + _fade_in->fast_simple_add ((len * 0.166667), 0.166366); + _fade_in->fast_simple_add ((len * 0.333333), 0.332853); + _fade_in->fast_simple_add ((len * 0.500000), 0.499459); + _fade_in->fast_simple_add ((len * 0.666667), 0.666186); + _fade_in->fast_simple_add ((len * 0.833333), 0.833033); + _fade_in->fast_simple_add (len, 1.0); + break; } _fade_in->thaw (); @@ -842,47 +874,67 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len) switch (shape) { case FadeFast: - _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (0.0, 1.0); _fade_out->fast_simple_add (len * 0.023041, 0.697222); _fade_out->fast_simple_add (len * 0.0553, 0.483333); _fade_out->fast_simple_add (len * 0.170507, 0.233333); _fade_out->fast_simple_add (len * 0.370968, 0.0861111); _fade_out->fast_simple_add (len * 0.610599, 0.0333333); - _fade_out->fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (1.0, 0.0); break; case FadeLogA: - _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (0, 1.0); _fade_out->fast_simple_add (len * 0.228111, 0.988889); _fade_out->fast_simple_add (len * 0.347926, 0.972222); _fade_out->fast_simple_add (len * 0.529954, 0.886111); _fade_out->fast_simple_add (len * 0.753456, 0.658333); _fade_out->fast_simple_add (len * 0.9262673, 0.308333); - _fade_out->fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len, 0.0); break; case FadeSlow: - _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (0.0, 1.0); _fade_out->fast_simple_add (len * 0.305556, 1); _fade_out->fast_simple_add (len * 0.548611, 0.991736); _fade_out->fast_simple_add (len * 0.759259, 0.931129); _fade_out->fast_simple_add (len * 0.918981, 0.68595); _fade_out->fast_simple_add (len * 0.976852, 0.22865); - _fade_out->fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len, 0.0); break; case FadeLogB: - _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (0.0, 1.0); _fade_out->fast_simple_add (len * 0.080645, 0.730556); _fade_out->fast_simple_add (len * 0.277778, 0.289256); _fade_out->fast_simple_add (len * 0.470046, 0.152778); _fade_out->fast_simple_add (len * 0.695853, 0.0694444); - _fade_out->fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len, 0.0); break; case FadeLinear: - _fade_out->fast_simple_add (len * 0, 1); - _fade_out->fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (0.0, 1.0); + _fade_out->fast_simple_add (len, 0.0); + break; + + case FadeConstantPowerMinus3dB: + _fade_out->fast_simple_add (0.0, 1.0); + _fade_out->fast_simple_add ((len * 0.166667), 0.948859); + _fade_out->fast_simple_add ((len * 0.333333), 0.851507); + _fade_out->fast_simple_add ((len * 0.500000), 0.707946); + _fade_out->fast_simple_add ((len * 0.666667), 0.518174); + _fade_out->fast_simple_add ((len * 0.833333), 0.282192); + _fade_out->fast_simple_add (len, 0.0); + break; + + case FadeConstantPowerMinus6dB: + _fade_out->fast_simple_add (0.0, 1.0); + _fade_out->fast_simple_add ((len * 0.166667), 0.833033); + _fade_out->fast_simple_add ((len * 0.333333), 0.666186); + _fade_out->fast_simple_add ((len * 0.500000), 0.499459); + _fade_out->fast_simple_add ((len * 0.666667), 0.332853); + _fade_out->fast_simple_add ((len * 0.833333), 0.166366); + _fade_out->fast_simple_add (len, 0.0); break; } @@ -957,6 +1009,7 @@ void AudioRegion::set_default_fade_in () { _fade_in_suspended = 0; + _fade_in_is_xfade = false; set_fade_in (FadeLinear, 64); } @@ -964,6 +1017,7 @@ void AudioRegion::set_default_fade_out () { _fade_out_suspended = 0; + _fade_out_is_xfade = false; set_fade_out (FadeLinear, 64); } @@ -1532,6 +1586,18 @@ AudioRegion::body_range () const return Evoral::Range<framepos_t> (first_frame() + _fade_in->back()->when, last_frame() - _fade_out->back()->when); } +void +AudioRegion::set_fade_in_is_xfade (bool yn) +{ + _fade_in_is_xfade = yn; +} + +void +AudioRegion::set_fade_out_is_xfade (bool yn) +{ + _fade_out_is_xfade = yn; +} + extern "C" { int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit) diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index 4559ed457d..eea971e197 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -73,6 +73,7 @@ setup_enum_writer () RemoteModel _RemoteModel; DenormalModel _DenormalModel; CrossfadeModel _CrossfadeModel; + CrossfadeChoice _CrossfadeChoice; InsertMergePolicy _InsertMergePolicy; ListenPosition _ListenPosition; SampleFormat _SampleFormat; @@ -257,6 +258,11 @@ setup_enum_writer () REGISTER_ENUM (ShortCrossfade); REGISTER (_CrossfadeModel); + REGISTER_ENUM (RegionFades); + REGISTER_ENUM (ConstantPowerMinus3dB); + REGISTER_ENUM (ConstantPowerMinus6dB); + REGISTER (_CrossfadeChoice); + REGISTER_ENUM (InsertMergeReject); REGISTER_ENUM (InsertMergeRelax); REGISTER_ENUM (InsertMergeReplace); @@ -411,6 +417,8 @@ setup_enum_writer () REGISTER_ENUM (FadeSlow); REGISTER_ENUM (FadeLogA); REGISTER_ENUM (FadeLogB); + REGISTER_ENUM (FadeConstantPowerMinus3dB); + REGISTER_ENUM (FadeConstantPowerMinus6dB); REGISTER (_FadeShape); REGISTER_CLASS_ENUM (Diskstream, Recordable); @@ -732,6 +740,21 @@ std::ostream& operator<<(std::ostream& o, const CrossfadeModel& var) std::string s = enum_2_string (var); return o << s; } + +std::istream& operator>>(std::istream& o, CrossfadeChoice& var) +{ + std::string s; + o >> s; + var = (CrossfadeChoice) string_2_enum (s, var); + return o; +} + +std::ostream& operator<<(std::ostream& o, const CrossfadeChoice& var) +{ + std::string s = enum_2_string (var); + return o << s; +} + std::istream& operator>>(std::istream& o, SyncSource& var) { std::string s; diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index b146f942bd..29be9ec49d 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -608,11 +608,7 @@ Playlist::flush_notifications (bool from_undo) */ } - if ( - ((regions_changed || pending_contents_change) && !in_set_state) || - pending_layering - ) { - + if (((regions_changed || pending_contents_change) && !in_set_state) || pending_layering) { relayer (); } @@ -2276,14 +2272,22 @@ Playlist::set_layer (boost::shared_ptr<Region> region, double new_layer) } void -Playlist::setup_layering_indices (RegionList const & regions) const +Playlist::setup_layering_indices (RegionList const & regions) { uint64_t j = 0; + list<Evoral::Range<framepos_t> > xf; + for (RegionList::const_iterator k = regions.begin(); k != regions.end(); ++k) { (*k)->set_layering_index (j++); + + Evoral::Range<framepos_t> r ((*k)->first_frame(), (*k)->last_frame()); + xf.push_back (r); } -} + /* now recheck the entire playlist for crossfades */ + + coalesce_and_check_crossfades (xf); +} /** Take the layering indices of each of our regions, compute the layers * that they should be on, and write the layers back to the regions. @@ -2677,12 +2681,6 @@ Playlist::shuffle (boost::shared_ptr<Region> region, int dir) if (moved) { relayer (); - - list<Evoral::Range<framepos_t> > xf; - xf.push_back (old_range); - xf.push_back (region->range ()); - coalesce_and_check_crossfades (xf); - notify_contents_changed(); } |