1c4bdb6cad2fd9dc5ccc7accc455e86e8d9ad8a4
[ardour.git] / libs / ardour / crossfade.cc
1 /*
2     Copyright (C) 2003-2006 Paul Davis 
3
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.
8
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.
13
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.
17
18     $Id$
19 */
20
21 #include <sigc++/bind.h>
22
23 #include <ardour/types.h>
24 #include <ardour/crossfade.h>
25 #include <ardour/crossfade_compare.h>
26 #include <ardour/audioregion.h>
27 #include <ardour/playlist.h>
28 #include <ardour/utils.h>
29 #include <ardour/session.h>
30
31 #include "i18n.h"
32 #include <locale.h>
33
34 using namespace std;
35 using namespace ARDOUR;
36 using namespace PBD;
37
38 nframes_t Crossfade::_short_xfade_length = 0;
39 Change Crossfade::ActiveChanged = new_change();
40 Change Crossfade::FollowOverlapChanged = new_change();
41
42 /* XXX if and when we ever implement parallel processing of the process()
43    callback, these will need to be handled on a per-thread basis.
44 */
45
46 Sample* Crossfade::crossfade_buffer_out = 0;
47 Sample* Crossfade::crossfade_buffer_in = 0;
48
49 void
50 Crossfade::set_buffer_size (nframes_t sz)
51 {
52         if (crossfade_buffer_out) {
53                 delete [] crossfade_buffer_out;
54                 crossfade_buffer_out = 0;
55         }
56
57         if (crossfade_buffer_in) {
58                 delete [] crossfade_buffer_in;
59                 crossfade_buffer_in = 0;
60         }
61
62         if (sz) {
63                 crossfade_buffer_out = new Sample[sz];
64                 crossfade_buffer_in = new Sample[sz];
65         }
66 }
67
68 bool
69 Crossfade::operator== (const Crossfade& other)
70 {
71         return (_in == other._in) && (_out == other._out);
72 }
73
74 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<AudioRegion> out, 
75                       nframes_t length,
76                       nframes_t position,
77                       AnchorPoint ap)
78         : _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
79           _fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
80 {
81         _in = in;
82         _out = out;
83         _length = length;
84         _position = position;
85         _anchor_point = ap;
86
87         switch (Config->get_xfade_model()) {
88         case ShortCrossfade:
89                 _follow_overlap = false;
90                 break;
91         default:
92                 _follow_overlap = true;
93         }
94
95         _active = Config->get_crossfades_active ();
96         _fixed = true;
97                 
98         initialize ();
99 }
100
101 Crossfade::Crossfade (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model, bool act)
102         : _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
103           _fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
104 {
105         _in_update = false;
106         _fixed = false;
107
108         if (compute (a, b, model)) {
109                 throw failed_constructor();
110         }
111
112         _active = act;
113
114         initialize ();
115
116 }
117
118 Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
119         :  _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
120            _fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
121 {
122         boost::shared_ptr<Region> r;
123         XMLProperty* prop;
124         LocaleGuard lg (X_("POSIX"));
125
126         /* we have to find the in/out regions before we can do anything else */
127
128         if ((prop = node.property ("in")) == 0) {
129                 error << _("Crossfade: no \"in\" region in state") << endmsg;
130                 throw failed_constructor();
131         }
132         
133         PBD::ID id (prop->value());
134
135         if ((r = playlist.find_region (id)) == 0) {
136                 error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
137                       << endmsg;
138                 throw failed_constructor();
139         }
140         
141         if ((_in = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
142                 throw failed_constructor();
143         }
144
145         if ((prop = node.property ("out")) == 0) {
146                 error << _("Crossfade: no \"out\" region in state") << endmsg;
147                 throw failed_constructor();
148         }
149
150         PBD::ID id2 (prop->value());
151
152         if ((r = playlist.find_region (id2)) == 0) {
153                 error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2, playlist.name())
154                       << endmsg;
155                 throw failed_constructor();
156         }
157         
158         if ((_out = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
159                 throw failed_constructor();
160         }
161
162         _length = 0;
163         initialize();
164         
165         if (set_state (node)) {
166                 throw failed_constructor();
167         }
168 }
169
170 Crossfade::Crossfade (const Crossfade &orig, boost::shared_ptr<AudioRegion> newin, boost::shared_ptr<AudioRegion> newout)
171         : _fade_in(orig._fade_in),
172           _fade_out(orig._fade_out)
173 {
174         _active           = orig._active;
175         _in_update        = orig._in_update;
176         _length           = orig._length;
177         _position         = orig._position;
178         _anchor_point     = orig._anchor_point;
179         _follow_overlap   = orig._follow_overlap;
180         _fixed            = orig._fixed;
181         
182         _in = newin;
183         _out = newout;
184
185         // copied from Crossfade::initialize()
186         _in_update = false;
187         
188         _out->suspend_fade_out ();
189         _in->suspend_fade_in ();
190
191         overlap_type = _in->coverage (_out->position(), _out->last_frame());
192
193         // Let's make sure the fade isn't too long
194         set_length(_length);
195 }
196
197
198 Crossfade::~Crossfade ()
199 {
200         Invalidated (this);
201 }
202
203 void
204 Crossfade::initialize ()
205 {
206         _in_update = false;
207         
208         _out->suspend_fade_out ();
209         _in->suspend_fade_in ();
210
211         _fade_out.freeze ();
212         _fade_out.clear ();
213         _fade_out.add (0.0, 1.0);
214         _fade_out.add ((_length * 0.1), 0.99);
215         _fade_out.add ((_length * 0.2), 0.97);
216         _fade_out.add ((_length * 0.8), 0.03);
217         _fade_out.add ((_length * 0.9), 0.01);
218         _fade_out.add (_length, 0.0);
219         _fade_out.thaw ();
220         
221         _fade_in.freeze ();
222         _fade_in.clear ();
223         _fade_in.add (0.0, 0.0);
224         _fade_in.add ((_length * 0.1),  0.01);
225         _fade_in.add ((_length * 0.2),  0.03);
226         _fade_in.add ((_length * 0.8),  0.97);
227         _fade_in.add ((_length * 0.9),  0.99);
228         _fade_in.add (_length, 1.0);
229         _fade_in.thaw ();
230
231         _in->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
232         _out->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
233
234         overlap_type = _in->coverage (_out->position(), _out->last_frame());
235 }       
236
237 int
238 Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model)
239 {
240         boost::shared_ptr<AudioRegion> top;
241         boost::shared_ptr<AudioRegion> bottom;
242         nframes_t short_xfade_length;
243
244         short_xfade_length = _short_xfade_length; 
245
246         if (a->layer() < b->layer()) {
247                 top = b;
248                 bottom = a;
249         } else {
250                 top = a;
251                 bottom = b;
252         }
253         
254         /* first check for matching ends */
255         
256         if (top->first_frame() == bottom->first_frame()) {
257                 
258                 /* Both regions start at the same point */
259                 
260                 if (top->last_frame() < bottom->last_frame()) {
261                         
262                         /* top ends before bottom, so put an xfade
263                            in at the end of top.
264                         */
265                         
266                         /* [-------- top ---------- ]
267                          * {====== bottom =====================}
268                          */
269
270                         _in = bottom;
271                         _out = top;
272
273                         if (top->last_frame() < short_xfade_length) {
274                                 _position = 0;
275                         } else {
276                                 _position = top->last_frame() - short_xfade_length;
277                         }
278
279                         _length = min (short_xfade_length, top->length());
280                         _follow_overlap = false;
281                         _anchor_point = EndOfIn;
282                         _active = true;
283                         _fixed = true;
284
285                 } else {
286                         /* top ends after (or same time) as bottom - no xfade
287                          */
288                         
289                         /* [-------- top ------------------------ ]
290                          * {====== bottom =====================}
291                          */
292
293                         throw NoCrossfadeHere();
294                 }
295                 
296         } else if (top->last_frame() == bottom->last_frame()) {
297                 
298                 /* Both regions end at the same point */
299                 
300                 if (top->first_frame() > bottom->first_frame()) {
301                         
302                         /* top starts after bottom, put an xfade in at the
303                            start of top
304                         */
305                         
306                         /*            [-------- top ---------- ]
307                          * {====== bottom =====================}
308                          */
309
310                         _in = top;
311                         _out = bottom;
312                         _position = top->first_frame();
313                         _length = min (short_xfade_length, top->length());
314                         _follow_overlap = false;
315                         _anchor_point = StartOfIn;
316                         _active = true;
317                         _fixed = true;
318                         
319                 } else {
320                         /* top starts before bottom - no xfade
321                          */
322
323                         /* [-------- top ------------------------ ]
324                          *    {====== bottom =====================}
325                          */
326
327                         throw NoCrossfadeHere();
328                 }
329
330         } else {
331         
332                 /* OK, time to do more regular overlapping */
333
334                 OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
335
336                 switch (ot) {
337                 case OverlapNone:
338                         /* should be NOTREACHED as a precondition of creating
339                            a new crossfade, but we need to handle it here.
340                         */
341                         throw NoCrossfadeHere();
342                         break;
343                         
344                 case OverlapInternal:
345                 case OverlapExternal:
346                         /* should be NOTREACHED because of tests above */
347                         throw NoCrossfadeHere();
348                         break;
349                         
350                 case OverlapEnd: /* top covers start of bottom but ends within it */
351
352                         /* [---- top ------------------------] 
353                          *                { ==== bottom ============ } 
354                          */ 
355
356                         _in = bottom;
357                         _out = top;
358                         _position = bottom->first_frame();
359                         _anchor_point = StartOfIn;
360
361                         if (model == FullCrossfade) {
362                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
363                                 /* leave active alone */
364                                 _follow_overlap = true;
365                         } else {
366                                 _length = min (short_xfade_length, top->length());
367                                 _active = true;
368                                 _follow_overlap = false;
369                                 
370                         }
371                         break;
372                         
373                 case OverlapStart:   /* top starts within bottom but covers bottom's end */
374
375                         /*                   { ==== top ============ } 
376                          *   [---- bottom -------------------] 
377                          */
378
379                         _in = top;
380                         _out = bottom;
381                         _position = top->first_frame();
382                         _anchor_point = StartOfIn;
383
384                         if (model == FullCrossfade) {
385                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
386                                 /* leave active alone */
387                                 _follow_overlap = true;
388                         } else {
389                                 _length = min (short_xfade_length, top->length());
390                                 _active = true;
391                                 _follow_overlap = false;
392                                 
393                         }
394                         
395                         break;
396                 }
397         }
398         
399         return 0;
400 }
401
402 nframes_t 
403 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, 
404                     float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n,
405                     nframes_t read_frames, nframes_t skip_frames)
406 {
407         nframes_t offset;
408         nframes_t to_write;
409
410         if (!_active) {
411                 return 0;
412         }
413
414         if (start < _position) {
415
416                 /* handle an initial section of the read area that we do not
417                    cover.
418                 */
419
420                 offset = _position - start;
421
422                 if (offset < cnt) {
423                         cnt -= offset;
424                 } else {
425                         return 0;
426                 }
427                 
428                 start = _position;
429                 buf += offset;
430                 to_write = min (_length, cnt);
431
432         } else {
433                 
434                 to_write = min (_length - (start - _position), cnt);
435                 
436         }
437
438         offset = start - _position;
439
440         _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
441         _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
442
443         float* fiv = new float[to_write];
444         float* fov = new float[to_write];
445
446         _fade_in.get_vector (offset, offset+to_write, fiv, to_write);
447         _fade_out.get_vector (offset, offset+to_write, fov, to_write);
448
449         /* note: although we have not explicitly taken into account the return values
450            from _out->read_at() or _in->read_at(), the length() function does this
451            implicitly. why? because it computes a value based on the in+out regions'
452            position and length, and so we know precisely how much data they could return. 
453         */
454
455         for (nframes_t n = 0; n < to_write; ++n) {
456                 buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
457         }
458
459         delete [] fov;
460         delete [] fiv;
461
462         return to_write;
463 }       
464
465 OverlapType 
466 Crossfade::coverage (nframes_t start, nframes_t end) const
467 {
468         nframes_t my_end = _position + _length;
469
470         if ((start >= _position) && (end <= my_end)) {
471                 return OverlapInternal;
472         }
473         if ((end >= _position) && (end <= my_end)) {
474                 return OverlapStart;
475         }
476         if ((start >= _position) && (start <= my_end)) {
477                 return OverlapEnd;
478         }
479         if ((_position >= start) && (_position <= end) && (my_end <= end)) {
480                 return OverlapExternal;
481         }
482         return OverlapNone;
483 }
484
485 void
486 Crossfade::set_active (bool yn)
487 {
488         if (_active != yn) {
489                 _active = yn;
490                 StateChanged (ActiveChanged);
491         }
492 }
493
494 bool
495 Crossfade::refresh ()
496 {
497         /* crossfades must be between non-muted regions */
498         
499         if (_out->muted() || _in->muted()) {
500                 Invalidated (this);
501                 return false;
502         }
503
504         /* overlap type must be Start, End or External */
505
506         OverlapType ot;
507         
508         ot = _in->coverage (_out->first_frame(), _out->last_frame());
509         
510         switch (ot) {
511         case OverlapNone:
512         case OverlapInternal:
513                 Invalidated (this);
514                 return false;
515                 
516         default:
517                 break;
518         }
519                 
520         /* overlap type must not have altered */
521         
522         if (ot != overlap_type) {
523                 Invalidated (this);
524                 return false;
525         } 
526
527         /* time to update */
528
529         return update (false);
530 }
531
532 bool
533 Crossfade::update (bool force)
534 {
535         nframes_t newlen;
536
537         if (_follow_overlap) {
538                 newlen = _out->first_frame() + _out->length() - _in->first_frame();
539         } else {
540                 newlen = _length;
541         }
542
543         if (newlen == 0) {
544                 Invalidated (this);
545                 return false;
546         }
547
548         _in_update = true;
549
550         if (force || (_follow_overlap && newlen != _length) || (_length > newlen)) {
551
552                 double factor =  newlen / (double) _length;
553                 
554                 _fade_out.x_scale (factor);
555                 _fade_in.x_scale (factor);
556                 
557                 _length = newlen;
558
559         } 
560
561         switch (_anchor_point) {
562         case StartOfIn:
563                 if (_position != _in->first_frame()) {
564                         _position = _in->first_frame();
565                 }
566                 break;
567
568         case EndOfIn:
569                 if (_position != _in->last_frame() - _length) {
570                         _position = _in->last_frame() - _length;
571                 }
572                 break;
573
574         case EndOfOut:
575                 if (_position != _out->last_frame() - _length) {
576                         _position = _out->last_frame() - _length;
577                 }
578         }
579
580         /* UI's may need to know that the overlap changed even 
581            though the xfade length did not.
582         */
583         
584         StateChanged (BoundsChanged); /* EMIT SIGNAL */
585
586         _in_update = false;
587
588         return true;
589 }
590
591 void
592 Crossfade::member_changed (Change what_changed)
593 {
594         Change what_we_care_about = Change (Region::MuteChanged|
595                                             Region::LayerChanged|
596                                             BoundsChanged);
597
598         if (what_changed & what_we_care_about) {
599                 refresh ();
600         }
601 }
602
603 XMLNode&
604 Crossfade::get_state () 
605 {
606         XMLNode* node = new XMLNode (X_("Crossfade"));
607         XMLNode* child;
608         char buf[64];
609         LocaleGuard lg (X_("POSIX"));
610
611         _out->id().print (buf, sizeof (buf));
612         node->add_property ("out", buf);
613         _in->id().print (buf, sizeof (buf));
614         node->add_property ("in", buf);
615         node->add_property ("active", (_active ? "yes" : "no"));
616         node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
617         node->add_property ("fixed", (_fixed ? "yes" : "no"));
618         snprintf (buf, sizeof(buf), "%" PRIu32, _length);
619         node->add_property ("length", buf);
620         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
621         node->add_property ("anchor-point", buf);
622         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
623         node->add_property ("position", buf);
624
625         child = node->add_child ("FadeIn");
626
627         for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.end(); ++ii) {
628                 XMLNode* pnode;
629
630                 pnode = new XMLNode ("point");
631
632                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
633                 pnode->add_property ("x", buf);
634                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
635                 pnode->add_property ("y", buf);
636                 child->add_child_nocopy (*pnode);
637         }
638
639         child = node->add_child ("FadeOut");
640
641         for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
642                 XMLNode* pnode;
643
644                 pnode = new XMLNode ("point");
645
646                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
647                 pnode->add_property ("x", buf);
648                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
649                 pnode->add_property ("y", buf);
650                 child->add_child_nocopy (*pnode);
651         }
652
653         return *node;
654 }
655
656 int
657 Crossfade::set_state (const XMLNode& node)
658 {
659         XMLNodeConstIterator i;
660         XMLNodeList children;
661         XMLNode* fi;
662         XMLNode* fo;
663         const XMLProperty* prop;
664         LocaleGuard lg (X_("POSIX"));
665         Change what_changed = Change (0);
666         nframes_t val;
667
668         if ((prop = node.property ("position")) != 0) {
669                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
670                 if (val != _position) {
671                         _position = val;
672                         what_changed = Change (what_changed | PositionChanged);
673                 }
674         } else {
675                 warning << _("old-style crossfade information - no position information") << endmsg;
676                 _position = _in->first_frame();
677         }
678
679         if ((prop = node.property ("active")) != 0) {
680                 bool x = (prop->value() == "yes");
681                 if (x != _active) {
682                         _active = x;
683                         what_changed = Change (what_changed | ActiveChanged);
684                 }
685         } else {
686                 _active = true;
687         }
688
689         if ((prop = node.property ("follow-overlap")) != 0) {
690                 _follow_overlap = (prop->value() == "yes");
691         } else {
692                 _follow_overlap = false;
693         }
694
695         if ((prop = node.property ("fixed")) != 0) {
696                 _fixed = (prop->value() == "yes");
697         } else {
698                 _fixed = false;
699         }
700
701         if ((prop = node.property ("anchor-point")) != 0) {
702                 _anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
703         } else {
704                 _anchor_point = StartOfIn;
705         }
706
707         if ((prop = node.property ("length")) != 0) {
708
709                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
710                 if (val != _length) {
711                         _length = atol (prop->value().c_str());
712                         what_changed = Change (what_changed | LengthChanged);
713                 }
714
715         } else {
716                 
717                 /* XXX this branch is legacy code from before
718                    the point where we stored xfade lengths.
719                 */
720                 
721                 if ((_length = overlap_length()) == 0) {
722                         throw failed_constructor();
723                 }
724         }
725
726         if ((fi = find_named_node (node, "FadeIn")) == 0) {
727                 return -1;
728         }
729         
730         if ((fo = find_named_node (node, "FadeOut")) == 0) {
731                 return -1;
732         }
733
734         /* fade in */
735         
736         _fade_in.freeze ();
737         _fade_in.clear ();
738         
739         children = fi->children();
740         
741         for (i = children.begin(); i != children.end(); ++i) {
742                 if ((*i)->name() == "point") {
743                         nframes_t x;
744                         float y;
745                         
746                         prop = (*i)->property ("x");
747                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
748                         
749                         prop = (*i)->property ("y");
750                         sscanf (prop->value().c_str(), "%f", &y);
751
752                         _fade_in.add (x, y);
753                 }
754         }
755
756         _fade_in.thaw ();
757         
758         /* fade out */
759         
760         _fade_in.freeze ();
761         _fade_out.clear ();
762
763         children = fo->children();
764         
765         for (i = children.begin(); i != children.end(); ++i) {
766                 if ((*i)->name() == "point") {
767                         nframes_t x;
768                         float y;
769                         XMLProperty* prop;
770
771                         prop = (*i)->property ("x");
772                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
773
774                         prop = (*i)->property ("y");
775                         sscanf (prop->value().c_str(), "%f", &y);
776                         
777                         _fade_out.add (x, y);
778                 }
779         }
780
781         _fade_out.thaw ();
782
783         StateChanged (what_changed); /* EMIT SIGNAL */
784
785         return 0;
786 }
787
788 bool
789 Crossfade::can_follow_overlap () const
790 {
791         return !_fixed;
792 }
793
794 void
795 Crossfade::set_follow_overlap (bool yn)
796 {
797         if (yn == _follow_overlap || _fixed) {
798                 return;
799         }
800
801         _follow_overlap = yn;
802
803         if (!yn) {
804                 set_length (_short_xfade_length);
805         } else {
806                 set_length (_out->first_frame() + _out->length() - _in->first_frame());
807         }
808
809         StateChanged (FollowOverlapChanged);
810 }
811
812 nframes_t
813 Crossfade::set_length (nframes_t len)
814 {
815         nframes_t limit;
816
817         switch (_anchor_point) {
818         case StartOfIn:
819                 limit = _in->length();
820                 break;
821
822         case EndOfIn:
823                 limit = _in->length();
824                 break;
825
826         case EndOfOut:
827                 limit = _out->length();
828                 break;
829                 
830         }
831
832         len = min (limit, len);
833
834         double factor = len / (double) _length;
835
836         _in_update = true;
837         _fade_out.x_scale (factor);
838         _fade_in.x_scale (factor);
839         _in_update = false;
840         
841         _length = len;
842
843         StateChanged (LengthChanged);
844
845         return len;
846 }
847
848 nframes_t
849 Crossfade::overlap_length () const
850 {
851         if (_fixed) {
852                 return _length;
853         }
854         return _out->first_frame() + _out->length() - _in->first_frame();
855 }
856
857 void
858 Crossfade::set_short_xfade_length (nframes_t n)
859 {
860         _short_xfade_length = n;
861 }
862
863 void
864 Crossfade::invalidate ()
865 {
866         Invalidated (this); /* EMIT SIGNAL */
867 }