summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-04-27 20:57:48 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-04-27 20:57:48 +0000
commitf78913cc99ffd13001b4c4daf625391be77e79d0 (patch)
tree7576a54e9312d9c3bbfd490671c3b2b6702a5c51
parentd1af0b89a847fbde9a30a95e0198380ff6f4e68d (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.cc13
-rw-r--r--libs/ardour/ardour/audioregion.h10
-rw-r--r--libs/ardour/ardour/playlist.h2
-rw-r--r--libs/ardour/ardour/session_configuration_vars.h1
-rw-r--r--libs/ardour/ardour/types.h12
-rw-r--r--libs/ardour/audio_playlist.cc40
-rw-r--r--libs/ardour/audioregion.cc86
-rw-r--r--libs/ardour/enums.cc23
-rw-r--r--libs/ardour/playlist.cc24
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();
}