739ea1cc0e5cc89654c1bd99fefefd6ddad0e733
[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_xfades_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         cerr << "Deleting xfade @ " << this << endl;
201         Invalidated (this);
202         cerr << "invalidation signal sent\n";
203 }
204
205 void
206 Crossfade::initialize ()
207 {
208         _in_update = false;
209         
210         _out->suspend_fade_out ();
211         _in->suspend_fade_in ();
212
213         _fade_out.freeze ();
214         _fade_out.clear ();
215         _fade_out.add (0.0, 1.0);
216         _fade_out.add ((_length * 0.1), 0.99);
217         _fade_out.add ((_length * 0.2), 0.97);
218         _fade_out.add ((_length * 0.8), 0.03);
219         _fade_out.add ((_length * 0.9), 0.01);
220         _fade_out.add (_length, 0.0);
221         _fade_out.thaw ();
222         
223         _fade_in.freeze ();
224         _fade_in.clear ();
225         _fade_in.add (0.0, 0.0);
226         _fade_in.add ((_length * 0.1),  0.01);
227         _fade_in.add ((_length * 0.2),  0.03);
228         _fade_in.add ((_length * 0.8),  0.97);
229         _fade_in.add ((_length * 0.9),  0.99);
230         _fade_in.add (_length, 1.0);
231         _fade_in.thaw ();
232
233         _in->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
234         _out->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
235
236         overlap_type = _in->coverage (_out->position(), _out->last_frame());
237 }       
238
239 int
240 Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioRegion> b, CrossfadeModel model)
241 {
242         boost::shared_ptr<AudioRegion> top;
243         boost::shared_ptr<AudioRegion> bottom;
244         nframes_t short_xfade_length;
245
246         short_xfade_length = _short_xfade_length; 
247
248         if (a->layer() < b->layer()) {
249                 top = b;
250                 bottom = a;
251         } else {
252                 top = a;
253                 bottom = b;
254         }
255         
256         /* first check for matching ends */
257         
258         if (top->first_frame() == bottom->first_frame()) {
259                 
260                 /* Both regions start at the same point */
261                 
262                 if (top->last_frame() < bottom->last_frame()) {
263                         
264                         /* top ends before bottom, so put an xfade
265                            in at the end of top.
266                         */
267                         
268                         /* [-------- top ---------- ]
269                          * {====== bottom =====================}
270                          */
271
272                         _in = bottom;
273                         _out = top;
274
275                         if (top->last_frame() < short_xfade_length) {
276                                 _position = 0;
277                         } else {
278                                 _position = top->last_frame() - short_xfade_length;
279                         }
280
281                         _length = min (short_xfade_length, top->length());
282                         _follow_overlap = false;
283                         _anchor_point = EndOfIn;
284                         _active = true;
285                         _fixed = true;
286
287                 } else {
288                         /* top ends after (or same time) as bottom - no xfade
289                          */
290                         
291                         /* [-------- top ------------------------ ]
292                          * {====== bottom =====================}
293                          */
294
295                         throw NoCrossfadeHere();
296                 }
297                 
298         } else if (top->last_frame() == bottom->last_frame()) {
299                 
300                 /* Both regions end at the same point */
301                 
302                 if (top->first_frame() > bottom->first_frame()) {
303                         
304                         /* top starts after bottom, put an xfade in at the
305                            start of top
306                         */
307                         
308                         /*            [-------- top ---------- ]
309                          * {====== bottom =====================}
310                          */
311
312                         _in = top;
313                         _out = bottom;
314                         _position = top->first_frame();
315                         _length = min (short_xfade_length, top->length());
316                         _follow_overlap = false;
317                         _anchor_point = StartOfIn;
318                         _active = true;
319                         _fixed = true;
320                         
321                 } else {
322                         /* top starts before bottom - no xfade
323                          */
324
325                         /* [-------- top ------------------------ ]
326                          *    {====== bottom =====================}
327                          */
328
329                         throw NoCrossfadeHere();
330                 }
331
332         } else {
333         
334                 /* OK, time to do more regular overlapping */
335
336                 OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
337
338                 switch (ot) {
339                 case OverlapNone:
340                         /* should be NOTREACHED as a precondition of creating
341                            a new crossfade, but we need to handle it here.
342                         */
343                         throw NoCrossfadeHere();
344                         break;
345                         
346                 case OverlapInternal:
347                 case OverlapExternal:
348                         /* should be NOTREACHED because of tests above */
349                         throw NoCrossfadeHere();
350                         break;
351                         
352                 case OverlapEnd: /* top covers start of bottom but ends within it */
353
354                         /* [---- top ------------------------] 
355                          *                { ==== bottom ============ } 
356                          */ 
357
358                         _in = bottom;
359                         _out = top;
360                         _position = bottom->first_frame();
361                         _anchor_point = StartOfIn;
362
363                         if (model == FullCrossfade) {
364                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
365                                 /* leave active alone */
366                                 _follow_overlap = true;
367                         } else {
368                                 _length = min (short_xfade_length, top->length());
369                                 _active = true;
370                                 _follow_overlap = false;
371                                 
372                         }
373                         break;
374                         
375                 case OverlapStart:   /* top starts within bottom but covers bottom's end */
376
377                         /*                   { ==== top ============ } 
378                          *   [---- bottom -------------------] 
379                          */
380
381                         _in = top;
382                         _out = bottom;
383                         _position = top->first_frame();
384                         _anchor_point = StartOfIn;
385
386                         if (model == FullCrossfade) {
387                                 _length = _out->first_frame() + _out->length() - _in->first_frame();
388                                 /* leave active alone */
389                                 _follow_overlap = true;
390                         } else {
391                                 _length = min (short_xfade_length, top->length());
392                                 _active = true;
393                                 _follow_overlap = false;
394                                 
395                         }
396                         
397                         break;
398                 }
399         }
400         
401         return 0;
402 }
403
404 nframes_t 
405 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, 
406                     float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n,
407                     nframes_t read_frames, nframes_t skip_frames)
408 {
409         nframes_t offset;
410         nframes_t to_write;
411
412         if (!_active) {
413                 return 0;
414         }
415
416         if (start < _position) {
417
418                 /* handle an initial section of the read area that we do not
419                    cover.
420                 */
421
422                 offset = _position - start;
423
424                 if (offset < cnt) {
425                         cnt -= offset;
426                 } else {
427                         return 0;
428                 }
429                 
430                 start = _position;
431                 buf += offset;
432                 to_write = min (_length, cnt);
433
434         } else {
435                 
436                 to_write = min (_length - (start - _position), cnt);
437                 
438         }
439
440         offset = start - _position;
441
442         _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
443         _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
444
445         float* fiv = new float[to_write];
446         float* fov = new float[to_write];
447
448         _fade_in.get_vector (offset, offset+to_write, fiv, to_write);
449         _fade_out.get_vector (offset, offset+to_write, fov, to_write);
450
451         /* note: although we have not explicitly taken into account the return values
452            from _out->read_at() or _in->read_at(), the length() function does this
453            implicitly. why? because it computes a value based on the in+out regions'
454            position and length, and so we know precisely how much data they could return. 
455         */
456
457         for (nframes_t n = 0; n < to_write; ++n) {
458                 buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
459         }
460
461         delete [] fov;
462         delete [] fiv;
463
464         return to_write;
465 }       
466
467 OverlapType 
468 Crossfade::coverage (nframes_t start, nframes_t end) const
469 {
470         nframes_t my_end = _position + _length;
471
472         if ((start >= _position) && (end <= my_end)) {
473                 return OverlapInternal;
474         }
475         if ((end >= _position) && (end <= my_end)) {
476                 return OverlapStart;
477         }
478         if ((start >= _position) && (start <= my_end)) {
479                 return OverlapEnd;
480         }
481         if ((_position >= start) && (_position <= end) && (my_end <= end)) {
482                 return OverlapExternal;
483         }
484         return OverlapNone;
485 }
486
487 void
488 Crossfade::set_active (bool yn)
489 {
490         if (_active != yn) {
491                 _active = yn;
492                 StateChanged (ActiveChanged);
493         }
494 }
495
496 bool
497 Crossfade::refresh ()
498 {
499         /* crossfades must be between non-muted regions */
500         
501         if (_out->muted() || _in->muted()) {
502                 Invalidated (this);
503                 return false;
504         }
505
506         /* overlap type must be Start, End or External */
507
508         OverlapType ot;
509         
510         ot = _in->coverage (_out->first_frame(), _out->last_frame());
511         
512         switch (ot) {
513         case OverlapNone:
514         case OverlapInternal:
515                 Invalidated (this);
516                 return false;
517                 
518         default:
519                 break;
520         }
521                 
522         /* overlap type must not have altered */
523         
524         if (ot != overlap_type) {
525                 Invalidated (this);
526                 return false;
527         } 
528
529         /* time to update */
530
531         return update (false);
532 }
533
534 bool
535 Crossfade::update (bool force)
536 {
537         nframes_t newlen;
538
539         if (_follow_overlap) {
540                 newlen = _out->first_frame() + _out->length() - _in->first_frame();
541         } else {
542                 newlen = _length;
543         }
544
545         if (newlen == 0) {
546                 Invalidated (this);
547                 return false;
548         }
549
550         _in_update = true;
551
552         if (force || (_follow_overlap && newlen != _length) || (_length > newlen)) {
553
554                 double factor =  newlen / (double) _length;
555                 
556                 _fade_out.x_scale (factor);
557                 _fade_in.x_scale (factor);
558                 
559                 _length = newlen;
560
561         } 
562
563         switch (_anchor_point) {
564         case StartOfIn:
565                 if (_position != _in->first_frame()) {
566                         _position = _in->first_frame();
567                 }
568                 break;
569
570         case EndOfIn:
571                 if (_position != _in->last_frame() - _length) {
572                         _position = _in->last_frame() - _length;
573                 }
574                 break;
575
576         case EndOfOut:
577                 if (_position != _out->last_frame() - _length) {
578                         _position = _out->last_frame() - _length;
579                 }
580         }
581
582         /* UI's may need to know that the overlap changed even 
583            though the xfade length did not.
584         */
585         
586         StateChanged (BoundsChanged); /* EMIT SIGNAL */
587
588         _in_update = false;
589
590         return true;
591 }
592
593 void
594 Crossfade::member_changed (Change what_changed)
595 {
596         Change what_we_care_about = Change (Region::MuteChanged|
597                                             Region::LayerChanged|
598                                             BoundsChanged);
599
600         if (what_changed & what_we_care_about) {
601                 refresh ();
602         }
603 }
604
605 XMLNode&
606 Crossfade::get_state () 
607 {
608         XMLNode* node = new XMLNode (X_("Crossfade"));
609         XMLNode* child;
610         char buf[64];
611         LocaleGuard lg (X_("POSIX"));
612
613         _out->id().print (buf, sizeof (buf));
614         node->add_property ("out", buf);
615         _in->id().print (buf, sizeof (buf));
616         node->add_property ("in", buf);
617         node->add_property ("active", (_active ? "yes" : "no"));
618         node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
619         node->add_property ("fixed", (_fixed ? "yes" : "no"));
620         snprintf (buf, sizeof(buf), "%" PRIu32, _length);
621         node->add_property ("length", buf);
622         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
623         node->add_property ("anchor-point", buf);
624         snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
625         node->add_property ("position", buf);
626
627         child = node->add_child ("FadeIn");
628
629         for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.end(); ++ii) {
630                 XMLNode* pnode;
631
632                 pnode = new XMLNode ("point");
633
634                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
635                 pnode->add_property ("x", buf);
636                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
637                 pnode->add_property ("y", buf);
638                 child->add_child_nocopy (*pnode);
639         }
640
641         child = node->add_child ("FadeOut");
642
643         for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
644                 XMLNode* pnode;
645
646                 pnode = new XMLNode ("point");
647
648                 snprintf (buf, sizeof (buf), "%" PRIu32, (nframes_t) floor ((*ii)->when));
649                 pnode->add_property ("x", buf);
650                 snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
651                 pnode->add_property ("y", buf);
652                 child->add_child_nocopy (*pnode);
653         }
654
655         return *node;
656 }
657
658 int
659 Crossfade::set_state (const XMLNode& node)
660 {
661         XMLNodeConstIterator i;
662         XMLNodeList children;
663         XMLNode* fi;
664         XMLNode* fo;
665         const XMLProperty* prop;
666         LocaleGuard lg (X_("POSIX"));
667         Change what_changed = Change (0);
668         nframes_t val;
669
670         if ((prop = node.property ("position")) != 0) {
671                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
672                 if (val != _position) {
673                         _position = val;
674                         what_changed = Change (what_changed | PositionChanged);
675                 }
676         } else {
677                 warning << _("old-style crossfade information - no position information") << endmsg;
678                 _position = _in->first_frame();
679         }
680
681         if ((prop = node.property ("active")) != 0) {
682                 bool x = (prop->value() == "yes");
683                 if (x != _active) {
684                         _active = x;
685                         what_changed = Change (what_changed | ActiveChanged);
686                 }
687         } else {
688                 _active = true;
689         }
690
691         if ((prop = node.property ("follow-overlap")) != 0) {
692                 _follow_overlap = (prop->value() == "yes");
693         } else {
694                 _follow_overlap = false;
695         }
696
697         if ((prop = node.property ("fixed")) != 0) {
698                 _fixed = (prop->value() == "yes");
699         } else {
700                 _fixed = false;
701         }
702
703         if ((prop = node.property ("anchor-point")) != 0) {
704                 _anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
705         } else {
706                 _anchor_point = StartOfIn;
707         }
708
709         if ((prop = node.property ("length")) != 0) {
710
711                 sscanf (prop->value().c_str(), "%" PRIu32, &val);
712                 if (val != _length) {
713                         _length = atol (prop->value().c_str());
714                         what_changed = Change (what_changed | LengthChanged);
715                 }
716
717         } else {
718                 
719                 /* XXX this branch is legacy code from before
720                    the point where we stored xfade lengths.
721                 */
722                 
723                 if ((_length = overlap_length()) == 0) {
724                         throw failed_constructor();
725                 }
726         }
727
728         if ((fi = find_named_node (node, "FadeIn")) == 0) {
729                 return -1;
730         }
731         
732         if ((fo = find_named_node (node, "FadeOut")) == 0) {
733                 return -1;
734         }
735
736         /* fade in */
737         
738         _fade_in.freeze ();
739         _fade_in.clear ();
740         
741         children = fi->children();
742         
743         for (i = children.begin(); i != children.end(); ++i) {
744                 if ((*i)->name() == "point") {
745                         nframes_t x;
746                         float y;
747                         
748                         prop = (*i)->property ("x");
749                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
750                         
751                         prop = (*i)->property ("y");
752                         sscanf (prop->value().c_str(), "%f", &y);
753
754                         _fade_in.add (x, y);
755                 }
756         }
757
758         _fade_in.thaw ();
759         
760         /* fade out */
761         
762         _fade_in.freeze ();
763         _fade_out.clear ();
764
765         children = fo->children();
766         
767         for (i = children.begin(); i != children.end(); ++i) {
768                 if ((*i)->name() == "point") {
769                         nframes_t x;
770                         float y;
771                         XMLProperty* prop;
772
773                         prop = (*i)->property ("x");
774                         sscanf (prop->value().c_str(), "%" PRIu32, &x);
775
776                         prop = (*i)->property ("y");
777                         sscanf (prop->value().c_str(), "%f", &y);
778                         
779                         _fade_out.add (x, y);
780                 }
781         }
782
783         _fade_out.thaw ();
784
785         StateChanged (what_changed); /* EMIT SIGNAL */
786
787         return 0;
788 }
789
790 bool
791 Crossfade::can_follow_overlap () const
792 {
793         return !_fixed;
794 }
795
796 void
797 Crossfade::set_follow_overlap (bool yn)
798 {
799         if (yn == _follow_overlap || _fixed) {
800                 return;
801         }
802
803         _follow_overlap = yn;
804
805         if (!yn) {
806                 set_length (_short_xfade_length);
807         } else {
808                 set_length (_out->first_frame() + _out->length() - _in->first_frame());
809         }
810
811         StateChanged (FollowOverlapChanged);
812 }
813
814 nframes_t
815 Crossfade::set_length (nframes_t len)
816 {
817         nframes_t limit;
818
819         switch (_anchor_point) {
820         case StartOfIn:
821                 limit = _in->length();
822                 break;
823
824         case EndOfIn:
825                 limit = _in->length();
826                 break;
827
828         case EndOfOut:
829                 limit = _out->length();
830                 break;
831                 
832         }
833
834         len = min (limit, len);
835
836         double factor = len / (double) _length;
837
838         _in_update = true;
839         _fade_out.x_scale (factor);
840         _fade_in.x_scale (factor);
841         _in_update = false;
842         
843         _length = len;
844
845         StateChanged (LengthChanged);
846
847         return len;
848 }
849
850 nframes_t
851 Crossfade::overlap_length () const
852 {
853         if (_fixed) {
854                 return _length;
855         }
856         return _out->first_frame() + _out->length() - _in->first_frame();
857 }
858
859 void
860 Crossfade::set_short_xfade_length (nframes_t n)
861 {
862         _short_xfade_length = n;
863 }
864
865 void
866 Crossfade::invalidate ()
867 {
868         Invalidated (this); /* EMIT SIGNAL */
869 }