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>
36 using namespace ARDOUR;
39 nframes_t Crossfade::_short_xfade_length = 0;
40 Change Crossfade::ActiveChanged = new_change();
41 Change Crossfade::FollowOverlapChanged = new_change();
43 /* XXX if and when we ever implement parallel processing of the process()
44 callback, these will need to be handled on a per-thread basis.
47 Sample* Crossfade::crossfade_buffer_out = 0;
48 Sample* Crossfade::crossfade_buffer_in = 0;
51 Crossfade::set_buffer_size (nframes_t sz)
53 if (crossfade_buffer_out) {
54 delete [] crossfade_buffer_out;
55 crossfade_buffer_out = 0;
58 if (crossfade_buffer_in) {
59 delete [] crossfade_buffer_in;
60 crossfade_buffer_in = 0;
64 crossfade_buffer_out = new Sample[sz];
65 crossfade_buffer_in = new Sample[sz];
70 Crossfade::operator== (const Crossfade& other)
72 return (_in == other._in) && (_out == other._out);
75 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<AudioRegion> out,
79 : _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
80 _fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
89 _follow_overlap = false;
91 _active = Config->get_xfades_active ();
97 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model, bool act)
98 : _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
99 _fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
104 if (compute (a, b, model)) {
105 throw failed_constructor();
113 Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
114 : _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
115 _fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
117 boost::shared_ptr<Region> r;
119 LocaleGuard lg (X_("POSIX"));
121 /* we have to find the in/out regions before we can do anything else */
123 if ((prop = node.property ("in")) == 0) {
124 error << _("Crossfade: no \"in\" region in state") << endmsg;
125 throw failed_constructor();
128 PBD::ID id (prop->value());
130 if ((r = playlist.find_region (id)) == 0) {
131 error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
133 throw failed_constructor();
136 if ((_in = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
137 throw failed_constructor();
140 if ((prop = node.property ("out")) == 0) {
141 error << _("Crossfade: no \"out\" region in state") << endmsg;
142 throw failed_constructor();
145 PBD::ID id2 (prop->value());
147 if ((r = playlist.find_region (id2)) == 0) {
148 error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2, playlist.name())
150 throw failed_constructor();
153 if ((_out = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
154 throw failed_constructor();
158 _active = Config->get_xfades_active();
162 if (set_state (node)) {
163 throw failed_constructor();
166 /* we should not need to do this here, since all values were set via XML. however
167 some older sessions may have bugs and this allows us to fix them.
173 Crossfade::Crossfade (const Crossfade &orig, boost::shared_ptr<AudioRegion> newin, boost::shared_ptr<AudioRegion> newout)
174 : _fade_in(orig._fade_in),
175 _fade_out(orig._fade_out)
177 _active = orig._active;
178 _in_update = orig._in_update;
179 _length = orig._length;
180 _position = orig._position;
181 _anchor_point = orig._anchor_point;
182 _follow_overlap = orig._follow_overlap;
183 _fixed = orig._fixed;
188 // copied from Crossfade::initialize()
191 _out->suspend_fade_out ();
192 _in->suspend_fade_in ();
194 overlap_type = _in->coverage (_out->position(), _out->last_frame());
195 layer_relation = (int32_t) (_in->layer() - _out->layer());
197 // Let's make sure the fade isn't too long
202 Crossfade::~Crossfade ()
208 Crossfade::initialize ()
212 _out->suspend_fade_out ();
213 _in->suspend_fade_in ();
218 #define EQUAL_POWER_MINUS_3DB
219 #ifdef EQUAL_POWER_MINUS_3DB
221 _fade_out.add ((_length * 0.000000), 1.000000);
222 _fade_out.add ((_length * 0.166667), 0.948859);
223 _fade_out.add ((_length * 0.333333), 0.851507);
224 _fade_out.add ((_length * 0.500000), 0.707946);
225 _fade_out.add ((_length * 0.666667), 0.518174);
226 _fade_out.add ((_length * 0.833333), 0.282192);
227 _fade_out.add ((_length * 1.000000), 0.000000);
229 #else // EQUAL_POWER_MINUS_6DB
231 _fade_out.add ((_length * 0.000000), 1.000000);
232 _fade_out.add ((_length * 0.166667), 0.833033);
233 _fade_out.add ((_length * 0.333333), 0.666186);
234 _fade_out.add ((_length * 0.500000), 0.499459);
235 _fade_out.add ((_length * 0.666667), 0.332853);
236 _fade_out.add ((_length * 0.833333), 0.166366);
237 _fade_out.add ((_length * 1.000000), 0.000000);
245 #define EQUAL_POWER_MINUS_3DB
246 #ifdef EQUAL_POWER_MINUS_3DB
248 _fade_in.add ((_length * 0.000000), 0.000000);
249 _fade_in.add ((_length * 0.166667), 0.282192);
250 _fade_in.add ((_length * 0.333333), 0.518174);
251 _fade_in.add ((_length * 0.500000), 0.707946);
252 _fade_in.add ((_length * 0.666667), 0.851507);
253 _fade_in.add ((_length * 0.833333), 0.948859);
254 _fade_in.add ((_length * 1.000000), 1.000000);
256 #else // EQUAL_POWER_MINUS_SIX_DB
258 _fade_in.add ((_length * 0.000000), 0.000000);
259 _fade_in.add ((_length * 0.166667), 0.166366);
260 _fade_in.add ((_length * 0.333333), 0.332853);
261 _fade_in.add ((_length * 0.500000), 0.499459);
262 _fade_in.add ((_length * 0.666667), 0.666186);
263 _fade_in.add ((_length * 0.833333), 0.833033);
264 _fade_in.add ((_length * 1.000000), 1.000000);
270 overlap_type = _in->coverage (_out->position(), _out->last_frame());
271 layer_relation = (int32_t) (_in->layer() - _out->layer());
275 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
276 float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n,
277 nframes_t read_frames, nframes_t skip_frames)
286 if (start < _position) {
288 /* handle an initial section of the read area that we do not
292 offset = _position - start;
302 to_write = min (_length, cnt);
306 to_write = min (_length - (start - _position), cnt);
310 offset = start - _position;
312 /* Prevent data from piling up inthe crossfade buffers when reading a transparent region */
313 if (!(_out->opaque())) {
314 memset (crossfade_buffer_out, 0, sizeof (Sample) * to_write);
315 } else if (!(_in->opaque())) {
316 memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
319 _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
320 _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
322 float* fiv = new float[to_write];
323 float* fov = new float[to_write];
325 _fade_in.get_vector (offset, offset+to_write, fiv, to_write);
326 _fade_out.get_vector (offset, offset+to_write, fov, to_write);
328 /* note: although we have not explicitly taken into account the return values
329 from _out->read_at() or _in->read_at(), the length() function does this
330 implicitly. why? because it computes a value based on the in+out regions'
331 position and length, and so we know precisely how much data they could return.
334 for (nframes_t n = 0; n < to_write; ++n) {
335 buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
345 Crossfade::coverage (nframes_t start, nframes_t end) const
347 nframes_t my_end = _position + _length;
349 if ((start >= _position) && (end <= my_end)) {
350 return OverlapInternal;
352 if ((end >= _position) && (end <= my_end)) {
355 if ((start >= _position) && (start <= my_end)) {
358 if ((_position >= start) && (_position <= end) && (my_end <= end)) {
359 return OverlapExternal;
365 Crossfade::set_active (bool yn)
369 StateChanged (ActiveChanged);
374 Crossfade::refresh ()
376 /* crossfades must be between non-muted regions */
378 if (_out->muted() || _in->muted()) {
379 Invalidated (shared_from_this());
383 /* Top layer shouldn't be transparent */
385 if (!((layer_relation > 0 ? _in : _out)->opaque())) {
386 Invalidated (shared_from_this());
390 /* layer ordering cannot change */
392 int32_t new_layer_relation = (int32_t) (_in->layer() - _out->layer());
394 if (new_layer_relation * layer_relation < 0) { // different sign, layers rotated
395 Invalidated (shared_from_this());
399 OverlapType ot = _in->coverage (_out->first_frame(), _out->last_frame());
401 if (ot == OverlapNone) {
402 Invalidated (shared_from_this());
408 if (ot != overlap_type) {
410 if (_follow_overlap) {
413 compute (_in, _out, Config->get_xfade_model());
416 catch (NoCrossfadeHere& err) {
417 Invalidated (shared_from_this());
425 Invalidated (shared_from_this());
431 send_signal = update ();
435 StateChanged (BoundsChanged); /* EMIT SIGNAL */
448 if (_follow_overlap) {
449 newlen = _out->first_frame() + _out->length() - _in->first_frame();
455 Invalidated (shared_from_this());
461 if ((_follow_overlap && newlen != _length) || (_length > newlen)) {
463 double factor = newlen / (double) _length;
465 _fade_out.x_scale (factor);
466 _fade_in.x_scale (factor);
471 switch (_anchor_point) {
473 _position = _in->first_frame();
477 _position = _in->last_frame() - _length + 1;
481 _position = _out->last_frame() - _length + 1;
488 Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model)
490 boost::shared_ptr<AudioRegion> top;
491 boost::shared_ptr<AudioRegion> bottom;
492 nframes_t short_xfade_length;
494 short_xfade_length = _short_xfade_length;
496 if (a->layer() < b->layer()) {
504 /* first check for matching ends */
506 if (top->first_frame() == bottom->first_frame()) {
508 /* Both regions start at the same point */
510 if (top->last_frame() < bottom->last_frame()) {
512 /* top ends before bottom, so put an xfade
513 in at the end of top.
516 /* [-------- top ---------- ]
517 * {====== bottom =====================}
523 if (top->last_frame() < short_xfade_length) {
526 _position = top->last_frame() - short_xfade_length;
529 _length = min (short_xfade_length, top->length());
530 _follow_overlap = false;
531 _anchor_point = EndOfIn;
536 /* top ends after (or same time) as bottom - no xfade
539 /* [-------- top ------------------------ ]
540 * {====== bottom =====================}
543 throw NoCrossfadeHere();
546 } else if (top->last_frame() == bottom->last_frame()) {
548 /* Both regions end at the same point */
550 if (top->first_frame() > bottom->first_frame()) {
552 /* top starts after bottom, put an xfade in at the
556 /* [-------- top ---------- ]
557 * {====== bottom =====================}
562 _position = top->first_frame();
563 _length = min (short_xfade_length, top->length());
564 _follow_overlap = false;
565 _anchor_point = StartOfIn;
570 /* top starts before bottom - no xfade
573 /* [-------- top ------------------------ ]
574 * {====== bottom =====================}
577 throw NoCrossfadeHere();
582 /* OK, time to do more regular overlapping */
584 OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
588 /* should be NOTREACHED as a precondition of creating
589 a new crossfade, but we need to handle it here.
591 throw NoCrossfadeHere();
594 case OverlapInternal:
595 case OverlapExternal:
596 /* should be NOTREACHED because of tests above */
597 throw NoCrossfadeHere();
600 case OverlapEnd: /* top covers start of bottom but ends within it */
602 /* [---- top ------------------------]
603 * { ==== bottom ============ }
608 _anchor_point = EndOfOut;
610 if (model == FullCrossfade) {
611 _position = bottom->first_frame(); // "{"
612 _length = _out->first_frame() + _out->length() - _in->first_frame();
613 /* leave active alone */
614 _follow_overlap = true;
616 _length = min (short_xfade_length, top->length());
617 _position = top->last_frame() - _length; // "]" - length
619 _follow_overlap = false;
624 case OverlapStart: /* top starts within bottom but covers bottom's end */
626 /* { ==== top ============ }
627 * [---- bottom -------------------]
632 _position = top->first_frame();
633 _anchor_point = StartOfIn;
635 if (model == FullCrossfade) {
636 _length = _out->first_frame() + _out->length() - _in->first_frame();
637 /* leave active alone */
638 _follow_overlap = true;
640 _length = min (short_xfade_length, top->length());
642 _follow_overlap = false;
654 Crossfade::get_state ()
656 XMLNode* node = new XMLNode (X_("Crossfade"));
659 LocaleGuard lg (X_("POSIX"));
661 _out->id().print (buf, sizeof (buf));
662 node->add_property ("out", buf);
663 _in->id().print (buf, sizeof (buf));
664 node->add_property ("in", buf);
665 node->add_property ("active", (_active ? "yes" : "no"));
666 node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
667 node->add_property ("fixed", (_fixed ? "yes" : "no"));
668 snprintf (buf, sizeof(buf), "%" PRIu32, _length);
669 node->add_property ("length", buf);
670 snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
671 node->add_property ("anchor-point", buf);
672 snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
673 node->add_property ("position", buf);
675 child = node->add_child ("FadeIn");
677 for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.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);
689 child = node->add_child ("FadeOut");
691 for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
694 pnode = new XMLNode ("point");
696 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
697 pnode->add_property ("x", buf);
698 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
699 pnode->add_property ("y", buf);
700 child->add_child_nocopy (*pnode);
707 Crossfade::set_state (const XMLNode& node)
709 XMLNodeConstIterator i;
710 XMLNodeList children;
713 const XMLProperty* prop;
714 LocaleGuard lg (X_("POSIX"));
715 Change what_changed = Change (0);
718 if ((prop = node.property ("position")) != 0) {
719 sscanf (prop->value().c_str(), "%" PRIu32, &val);
720 if (val != _position) {
722 what_changed = Change (what_changed | PositionChanged);
725 warning << _("old-style crossfade information - no position information") << endmsg;
726 _position = _in->first_frame();
729 if ((prop = node.property ("active")) != 0) {
730 bool x = (prop->value() == "yes");
733 what_changed = Change (what_changed | ActiveChanged);
739 if ((prop = node.property ("follow-overlap")) != 0) {
740 _follow_overlap = (prop->value() == "yes");
742 _follow_overlap = false;
745 if ((prop = node.property ("fixed")) != 0) {
746 _fixed = (prop->value() == "yes");
751 if ((prop = node.property ("anchor-point")) != 0) {
752 _anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
754 _anchor_point = StartOfIn;
757 if ((prop = node.property ("length")) != 0) {
759 sscanf (prop->value().c_str(), "%" PRIu32, &val);
760 if (val != _length) {
761 _length = atol (prop->value().c_str());
762 what_changed = Change (what_changed | LengthChanged);
767 /* XXX this branch is legacy code from before
768 the point where we stored xfade lengths.
771 if ((_length = overlap_length()) == 0) {
772 throw failed_constructor();
776 if ((fi = find_named_node (node, "FadeIn")) == 0) {
780 if ((fo = find_named_node (node, "FadeOut")) == 0) {
789 children = fi->children();
791 for (i = children.begin(); i != children.end(); ++i) {
792 if ((*i)->name() == "point") {
796 prop = (*i)->property ("x");
797 sscanf (prop->value().c_str(), "%" PRIu32, &x);
799 prop = (*i)->property ("y");
800 sscanf (prop->value().c_str(), "%f", &y);
813 children = fo->children();
815 for (i = children.begin(); i != children.end(); ++i) {
816 if ((*i)->name() == "point") {
821 prop = (*i)->property ("x");
822 sscanf (prop->value().c_str(), "%" PRIu32, &x);
824 prop = (*i)->property ("y");
825 sscanf (prop->value().c_str(), "%f", &y);
827 _fade_out.add (x, y);
833 StateChanged (what_changed); /* EMIT SIGNAL */
839 Crossfade::can_follow_overlap () const
845 Crossfade::set_follow_overlap (bool yn)
847 if (yn == _follow_overlap || _fixed) {
851 _follow_overlap = yn;
854 set_length (_short_xfade_length);
856 set_length (_out->first_frame() + _out->length() - _in->first_frame());
859 StateChanged (FollowOverlapChanged);
863 Crossfade::set_length (nframes_t len)
867 switch (_anchor_point) {
869 limit = _in->length();
873 limit = _in->length();
877 limit = _out->length();
882 len = min (limit, len);
884 double factor = len / (double) _length;
887 _fade_out.x_scale (factor);
888 _fade_in.x_scale (factor);
893 StateChanged (LengthChanged);
899 Crossfade::overlap_length () const
904 return _out->first_frame() + _out->length() - _in->first_frame();
908 Crossfade::set_short_xfade_length (nframes_t n)
910 _short_xfade_length = n;
914 Crossfade::invalidate ()
916 Invalidated (shared_from_this()); /* EMIT SIGNAL */