2 Copyright (C) 2003-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <sigc++/bind.h>
22 #include <pbd/stacktrace.h>
24 #include <ardour/types.h>
25 #include <ardour/crossfade.h>
26 #include <ardour/crossfade_compare.h>
27 #include <ardour/audioregion.h>
28 #include <ardour/playlist.h>
29 #include <ardour/utils.h>
30 #include <ardour/session.h>
31 #include <ardour/source.h>
37 using namespace ARDOUR;
40 nframes_t Crossfade::_short_xfade_length = 0;
41 Change Crossfade::ActiveChanged = new_change();
42 Change Crossfade::FollowOverlapChanged = new_change();
44 /* XXX if and when we ever implement parallel processing of the process()
45 callback, these will need to be handled on a per-thread basis.
48 Sample* Crossfade::crossfade_buffer_out = 0;
49 Sample* Crossfade::crossfade_buffer_in = 0;
52 Crossfade::set_buffer_size (nframes_t sz)
54 if (crossfade_buffer_out) {
55 delete [] crossfade_buffer_out;
56 crossfade_buffer_out = 0;
59 if (crossfade_buffer_in) {
60 delete [] crossfade_buffer_in;
61 crossfade_buffer_in = 0;
65 crossfade_buffer_out = new Sample[sz];
66 crossfade_buffer_in = new Sample[sz];
71 Crossfade::operator== (const Crossfade& other)
73 return (_in == other._in) && (_out == other._out);
76 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<AudioRegion> out,
80 : AudioRegion (in->session(), position, length, "foobar"),
81 _fade_in (Evoral::Parameter(FadeInAutomation)), // linear (gain coefficient) => -inf..+6dB
82 _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
88 _follow_overlap = false;
90 _active = Config->get_xfades_active ();
96 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model, bool act)
97 : AudioRegion (a->session(), 0, 0, "foobar"),
98 _fade_in (Evoral::Parameter(FadeInAutomation)), // linear (gain coefficient) => -inf..+6dB
99 _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
104 if (compute (a, b, model)) {
105 throw failed_constructor();
115 Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
116 : AudioRegion (playlist.session(), 0, 0, "foobar"),
117 _fade_in (Evoral::Parameter(FadeInAutomation)), // linear (gain coefficient) => -inf..+6dB
118 _fade_out (Evoral::Parameter(FadeOutAutomation)) // linear (gain coefficient) => -inf..+6dB
121 boost::shared_ptr<Region> r;
123 LocaleGuard lg (X_("POSIX"));
125 /* we have to find the in/out regions before we can do anything else */
127 if ((prop = node.property ("in")) == 0) {
128 error << _("Crossfade: no \"in\" region in state") << endmsg;
129 throw failed_constructor();
132 PBD::ID id (prop->value());
134 if ((r = playlist.find_region (id)) == 0) {
135 error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
137 throw failed_constructor();
140 if ((_in = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
141 throw failed_constructor();
144 if ((prop = node.property ("out")) == 0) {
145 error << _("Crossfade: no \"out\" region in state") << endmsg;
146 throw failed_constructor();
149 PBD::ID id2 (prop->value());
151 if ((r = playlist.find_region (id2)) == 0) {
152 error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2, playlist.name())
154 throw failed_constructor();
157 if ((_out = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
158 throw failed_constructor();
165 if (set_state (node)) {
166 throw failed_constructor();
170 Crossfade::Crossfade (boost::shared_ptr<Crossfade> orig, boost::shared_ptr<AudioRegion> newin, boost::shared_ptr<AudioRegion> newout)
171 : AudioRegion (boost::dynamic_pointer_cast<const AudioRegion> (orig)),
172 _fade_in (orig->_fade_in),
173 _fade_out (orig->_fade_out)
175 _active = orig->_active;
176 _in_update = orig->_in_update;
177 _anchor_point = orig->_anchor_point;
178 _follow_overlap = orig->_follow_overlap;
179 _fixed = orig->_fixed;
184 // copied from Crossfade::initialize()
187 _out->suspend_fade_out ();
188 _in->suspend_fade_in ();
190 overlap_type = _in->coverage (_out->position(), _out->last_frame());
191 layer_relation = (int32_t) (_in->layer() - _out->layer());
193 // Let's make sure the fade isn't too long
198 Crossfade::~Crossfade ()
204 Crossfade::initialize ()
206 /* merge source lists from regions */
208 _sources = _in->sources();
209 _sources.insert (_sources.end(), _out->sources().begin(), _out->sources().end());
210 _master_sources = _in->master_sources();
211 _master_sources.insert(_master_sources.end(), _out->master_sources().begin(), _out->master_sources().end());
215 _out->suspend_fade_out ();
216 _in->suspend_fade_in ();
220 _fade_out.add (0.0, 1.0);
221 _fade_out.add ((_length * 0.1), 0.99);
222 _fade_out.add ((_length * 0.2), 0.97);
223 _fade_out.add ((_length * 0.8), 0.03);
224 _fade_out.add ((_length * 0.9), 0.01);
225 _fade_out.add (_length, 0.0);
230 _fade_in.add (0.0, 0.0);
231 _fade_in.add ((_length * 0.1), 0.01);
232 _fade_in.add ((_length * 0.2), 0.03);
233 _fade_in.add ((_length * 0.8), 0.97);
234 _fade_in.add ((_length * 0.9), 0.99);
235 _fade_in.add (_length, 1.0);
238 overlap_type = _in->coverage (_out->position(), _out->last_frame());
239 layer_relation = (int32_t) (_in->layer() - _out->layer());
243 Crossfade::read_raw_internal (Sample* buf, nframes_t start, nframes_t cnt) const
246 Sample* mixdown = new Sample[cnt];
247 float* gain = new float[cnt];
250 ret = read_at (buf, mixdown, gain, start, cnt, chan_n, cnt);
261 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
262 float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n,
263 nframes_t read_frames, nframes_t skip_frames) const
272 if (start < _position) {
274 /* handle an initial section of the read area that we do not
278 offset = _position - start;
288 to_write = min (_length, cnt);
292 to_write = min (_length - (start - _position), cnt);
296 offset = start - _position;
298 /* Prevent data from piling up inthe crossfade buffers when reading a transparent region */
299 if (!(_out->opaque())) {
300 memset (crossfade_buffer_out, 0, sizeof (Sample) * to_write);
301 } else if (!(_in->opaque())) {
302 memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
305 _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
306 _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
308 float* fiv = new float[to_write];
309 float* fov = new float[to_write];
311 _fade_in.curve().get_vector (offset, offset+to_write, fiv, to_write);
312 _fade_out.curve().get_vector (offset, offset+to_write, fov, to_write);
314 /* note: although we have not explicitly taken into account the return values
315 from _out->read_at() or _in->read_at(), the length() function does this
316 implicitly. why? because it computes a value based on the in+out regions'
317 position and length, and so we know precisely how much data they could return.
320 for (nframes_t n = 0; n < to_write; ++n) {
321 buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
331 Crossfade::coverage (nframes_t start, nframes_t end) const
333 nframes_t my_end = _position + _length;
335 if ((start >= _position) && (end <= my_end)) {
336 return OverlapInternal;
338 if ((end >= _position) && (end <= my_end)) {
341 if ((start >= _position) && (start <= my_end)) {
344 if ((_position >= start) && (_position <= end) && (my_end <= end)) {
345 return OverlapExternal;
351 Crossfade::set_active (bool yn)
355 StateChanged (ActiveChanged);
360 Crossfade::refresh ()
362 /* crossfades must be between non-muted regions */
364 if (_out->muted() || _in->muted()) {
365 Invalidated (shared_from_this ());
369 /* Top layer shouldn't be transparent */
371 if (!((layer_relation > 0 ? _in : _out)->opaque())) {
372 Invalidated (shared_from_this());
376 /* layer ordering cannot change */
378 int32_t new_layer_relation = (int32_t) (_in->layer() - _out->layer());
380 if (new_layer_relation * layer_relation < 0) { // different sign, layers rotated
381 Invalidated (shared_from_this ());
385 OverlapType ot = _in->coverage (_out->first_frame(), _out->last_frame());
387 if (ot == OverlapNone) {
388 Invalidated (shared_from_this ());
394 if (ot != overlap_type) {
396 if (_follow_overlap) {
399 compute (_in, _out, Config->get_xfade_model());
402 catch (NoCrossfadeHere& err) {
403 Invalidated (shared_from_this ());
411 Invalidated (shared_from_this ());
417 send_signal = update ();
421 StateChanged (BoundsChanged); /* EMIT SIGNAL */
434 if (_follow_overlap) {
435 newlen = _out->first_frame() + _out->length() - _in->first_frame();
441 Invalidated (shared_from_this ());
447 if ((_follow_overlap && newlen != _length) || (_length > newlen)) {
449 double factor = newlen / (double) _length;
451 _fade_out.x_scale (factor);
452 _fade_in.x_scale (factor);
457 switch (_anchor_point) {
459 _position = _in->first_frame();
463 _position = _in->last_frame() - _length;
467 _position = _out->last_frame() - _length;
474 Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model)
476 boost::shared_ptr<AudioRegion> top;
477 boost::shared_ptr<AudioRegion> bottom;
478 nframes_t short_xfade_length;
480 short_xfade_length = _short_xfade_length;
482 if (a->layer() < b->layer()) {
490 /* first check for matching ends */
492 if (top->first_frame() == bottom->first_frame()) {
494 /* Both regions start at the same point */
496 if (top->last_frame() < bottom->last_frame()) {
498 /* top ends before bottom, so put an xfade
499 in at the end of top.
502 /* [-------- top ---------- ]
503 * {====== bottom =====================}
509 if (top->last_frame() < short_xfade_length) {
512 _position = top->last_frame() - short_xfade_length;
515 _length = min (short_xfade_length, top->length());
516 _follow_overlap = false;
517 _anchor_point = EndOfIn;
522 /* top ends after (or same time) as bottom - no xfade
525 /* [-------- top ------------------------ ]
526 * {====== bottom =====================}
529 throw NoCrossfadeHere();
532 } else if (top->last_frame() == bottom->last_frame()) {
534 /* Both regions end at the same point */
536 if (top->first_frame() > bottom->first_frame()) {
538 /* top starts after bottom, put an xfade in at the
542 /* [-------- top ---------- ]
543 * {====== bottom =====================}
548 _position = top->first_frame();
549 _length = min (short_xfade_length, top->length());
550 _follow_overlap = false;
551 _anchor_point = StartOfIn;
556 /* top starts before bottom - no xfade
559 /* [-------- top ------------------------ ]
560 * {====== bottom =====================}
563 throw NoCrossfadeHere();
568 /* OK, time to do more regular overlapping */
570 OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
574 /* should be NOTREACHED as a precondition of creating
575 a new crossfade, but we need to handle it here.
577 throw NoCrossfadeHere();
580 case OverlapInternal:
581 case OverlapExternal:
582 /* should be NOTREACHED because of tests above */
583 throw NoCrossfadeHere();
586 case OverlapEnd: /* top covers start of bottom but ends within it */
588 /* [---- top ------------------------]
589 * { ==== bottom ============ }
594 _anchor_point = EndOfOut;
596 if (model == FullCrossfade) {
597 _position = bottom->first_frame(); // "{"
598 _length = _out->first_frame() + _out->length() - _in->first_frame();
599 /* leave active alone */
600 _follow_overlap = true;
602 _length = min (short_xfade_length, top->length());
603 _position = top->last_frame() - _length; // "]" - length
605 _follow_overlap = false;
610 case OverlapStart: /* top starts within bottom but covers bottom's end */
612 /* { ==== top ============ }
613 * [---- bottom -------------------]
618 _position = top->first_frame();
619 _anchor_point = StartOfIn;
621 if (model == FullCrossfade) {
622 _length = _out->first_frame() + _out->length() - _in->first_frame();
623 /* leave active alone */
624 _follow_overlap = true;
626 _length = min (short_xfade_length, top->length());
628 _follow_overlap = false;
640 Crossfade::get_state ()
642 XMLNode* node = new XMLNode (X_("Crossfade"));
645 LocaleGuard lg (X_("POSIX"));
647 _out->id().print (buf, sizeof (buf));
648 node->add_property ("out", buf);
649 _in->id().print (buf, sizeof (buf));
650 node->add_property ("in", buf);
651 node->add_property ("active", (_active ? "yes" : "no"));
652 node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
653 node->add_property ("fixed", (_fixed ? "yes" : "no"));
654 snprintf (buf, sizeof(buf), "%" PRIu32, _length);
655 node->add_property ("length", buf);
656 snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
657 node->add_property ("anchor-point", buf);
658 snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
659 node->add_property ("position", buf);
661 child = node->add_child ("FadeIn");
663 for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.end(); ++ii) {
666 pnode = new XMLNode ("point");
668 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
669 pnode->add_property ("x", buf);
670 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
671 pnode->add_property ("y", buf);
672 child->add_child_nocopy (*pnode);
675 child = node->add_child ("FadeOut");
677 for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
680 pnode = new XMLNode ("point");
682 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
683 pnode->add_property ("x", buf);
684 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
685 pnode->add_property ("y", buf);
686 child->add_child_nocopy (*pnode);
693 Crossfade::set_state (const XMLNode& node)
695 XMLNodeConstIterator i;
696 XMLNodeList children;
699 const XMLProperty* prop;
700 LocaleGuard lg (X_("POSIX"));
701 Change what_changed = Change (0);
704 if ((prop = node.property ("position")) != 0) {
705 sscanf (prop->value().c_str(), "%" PRIu32, &val);
706 if (val != _position) {
708 what_changed = Change (what_changed | PositionChanged);
711 warning << _("old-style crossfade information - no position information") << endmsg;
712 _position = _in->first_frame();
715 if ((prop = node.property ("active")) != 0) {
716 bool x = (prop->value() == "yes");
719 what_changed = Change (what_changed | ActiveChanged);
725 if ((prop = node.property ("follow-overlap")) != 0) {
726 _follow_overlap = (prop->value() == "yes");
728 _follow_overlap = false;
731 if ((prop = node.property ("fixed")) != 0) {
732 _fixed = (prop->value() == "yes");
737 if ((prop = node.property ("anchor-point")) != 0) {
738 _anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
740 _anchor_point = StartOfIn;
743 if ((prop = node.property ("length")) != 0) {
745 sscanf (prop->value().c_str(), "%" PRIu32, &val);
746 if (val != _length) {
747 _length = atol (prop->value().c_str());
748 what_changed = Change (what_changed | LengthChanged);
753 /* XXX this branch is legacy code from before
754 the point where we stored xfade lengths.
757 if ((_length = overlap_length()) == 0) {
758 throw failed_constructor();
762 if ((fi = find_named_node (node, "FadeIn")) == 0) {
766 if ((fo = find_named_node (node, "FadeOut")) == 0) {
775 children = fi->children();
777 for (i = children.begin(); i != children.end(); ++i) {
778 if ((*i)->name() == "point") {
782 prop = (*i)->property ("x");
783 sscanf (prop->value().c_str(), "%" PRIu32, &x);
785 prop = (*i)->property ("y");
786 sscanf (prop->value().c_str(), "%f", &y);
799 children = fo->children();
801 for (i = children.begin(); i != children.end(); ++i) {
802 if ((*i)->name() == "point") {
807 prop = (*i)->property ("x");
808 sscanf (prop->value().c_str(), "%" PRIu32, &x);
810 prop = (*i)->property ("y");
811 sscanf (prop->value().c_str(), "%f", &y);
813 _fade_out.add (x, y);
819 StateChanged (what_changed); /* EMIT SIGNAL */
825 Crossfade::can_follow_overlap () const
831 Crossfade::set_follow_overlap (bool yn)
833 if (yn == _follow_overlap || _fixed) {
837 _follow_overlap = yn;
840 set_length (_short_xfade_length);
842 set_length (_out->first_frame() + _out->length() - _in->first_frame());
845 StateChanged (FollowOverlapChanged);
849 Crossfade::set_length (nframes_t len)
853 switch (_anchor_point) {
855 limit = _in->length();
859 limit = _in->length();
863 limit = _out->length();
868 len = min (limit, len);
870 double factor = len / (double) _length;
873 _fade_out.x_scale (factor);
874 _fade_in.x_scale (factor);
879 StateChanged (LengthChanged);
885 Crossfade::overlap_length () const
890 return _out->first_frame() + _out->length() - _in->first_frame();
894 Crossfade::set_short_xfade_length (nframes_t n)
896 _short_xfade_length = n;
900 Crossfade::invalidate ()
902 Invalidated (shared_from_this ()); /* EMIT SIGNAL */