Crossfades: default xfades are now constant-power, -3dB rule, other options are const...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 27 Apr 2012 20:57:48 +0000 (20:57 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 27 Apr 2012 20:57:48 +0000 (20:57 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12113 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/session_option_editor.cc
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/session_configuration_vars.h
libs/ardour/ardour/types.h
libs/ardour/audio_playlist.cc
libs/ardour/audioregion.cc
libs/ardour/enums.cc
libs/ardour/playlist.cc

index 62d555c13dc6ec66c68ac967eec8f4d7c0b684f5..fe9e06c3a3aff5c12a665d34f79e4042e5b1e1ac 100644 (file)
@@ -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"),
index 7236cd69a95b0f501f40c3c460290431b7c2f6fe..87d515d39975323eb9188630c2bf69e10ca87390 100644 (file)
@@ -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 */
index d57df6999b5fe32f9910f9dc2b993861d00b716b..559a24062b60f691fc985c1a4eb1c6fc8916a538 100644 (file)
@@ -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);
 };
index a6147f91405a31b1cdb5179f0c82c17ca4dc7652..16ce36020b540fce97edc369862938e7399b5d47 100644 (file)
@@ -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)
index b3c1666dbbd33e30f659a3f0c6ae900405baa90d..71c00e7520ebba2395d154bab9a51cdf1cf6e573 100644 (file)
@@ -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);
index ebebc62c3385e262d9305cc69abf2ee757f3add7..f1c89cc5657e4572abb710aefe2f51c7b8d52962 100644 (file)
@@ -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);
                                }
                        }
                }
index 8992f8ccca8da847036925504804aa78d2e908a8..79ee58b410078f9b8675bc178c56b669743ed852 100644 (file)
@@ -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)
index 4559ed457d710a2128167db8171e2cf9f69d3d07..eea971e197808466758c68106642dc1d67477888 100644 (file)
@@ -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;
index b146f942bdcc1273860b22f44254d3f66498863f..29be9ec49da120632cd57ff5593f471d114d47d6 100644 (file)
@@ -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();
        }