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