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.
21 #include "pbd/stacktrace.h"
23 #include "ardour/debug.h"
24 #include "ardour/types.h"
25 #include "ardour/crossfade.h"
26 #include "ardour/crossfade_compare.h"
27 #include "ardour/audioregion.h"
28 #include "ardour/playlist.h"
29 #include "ardour/utils.h"
30 #include "ardour/session.h"
31 #include "ardour/source.h"
37 using namespace ARDOUR
;
40 framecnt_t
Crossfade::_short_xfade_length
= 0;
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.
46 Sample
* Crossfade::crossfade_buffer_out
= 0;
47 Sample
* Crossfade::crossfade_buffer_in
= 0;
50 #define CROSSFADE_DEFAULT_PROPERTIES \
51 _active (Properties::active, _session.config.get_xfades_active ()) \
52 , _follow_overlap (Properties::follow_overlap, false)
56 namespace Properties
{
57 PropertyDescriptor
<bool> follow_overlap
;
62 Crossfade::make_property_quarks ()
64 Properties::follow_overlap
.property_id
= g_quark_from_static_string (X_("follow-overlap"));
65 DEBUG_TRACE (DEBUG::Properties
, string_compose ("quark for follow-overlap = %1\n", Properties::follow_overlap
.property_id
));
69 Crossfade::set_buffer_size (framecnt_t sz
)
71 delete [] crossfade_buffer_out
;
72 crossfade_buffer_out
= 0;
74 delete [] crossfade_buffer_in
;
75 crossfade_buffer_in
= 0;
78 crossfade_buffer_out
= new Sample
[sz
];
79 crossfade_buffer_in
= new Sample
[sz
];
84 Crossfade::operator== (const Crossfade
& other
)
86 return (_in
== other
._in
) && (_out
== other
._out
);
89 Crossfade::Crossfade (boost::shared_ptr
<AudioRegion
> in
, boost::shared_ptr
<AudioRegion
> out
,
93 : AudioRegion (in
->session(), position
, length
, in
->name() + string ("<>") + out
->name())
94 , CROSSFADE_DEFAULT_PROPERTIES
95 , _fade_in (Evoral::Parameter(FadeInAutomation
)) // linear (gain coefficient) => -inf..+6dB
96 , _fade_out (Evoral::Parameter(FadeOutAutomation
)) // linear (gain coefficient) => -inf..+6dB
103 _follow_overlap
= false;
108 Crossfade::Crossfade (boost::shared_ptr
<AudioRegion
> a
, boost::shared_ptr
<AudioRegion
> b
, CrossfadeModel model
, bool act
)
109 : AudioRegion (a
->session(), 0, 0, a
->name() + string ("<>") + b
->name())
110 , CROSSFADE_DEFAULT_PROPERTIES
111 , _fade_in (Evoral::Parameter(FadeInAutomation
)) // linear (gain coefficient) => -inf..+6dB
112 , _fade_out (Evoral::Parameter(FadeOutAutomation
)) // linear (gain coefficient) => -inf..+6dB
116 _follow_overlap
= false;
118 if (compute (a
, b
, model
)) {
119 throw failed_constructor();
127 Crossfade::Crossfade (const Playlist
& playlist
, XMLNode
& node
)
128 : AudioRegion (playlist
.session(), 0, 0, "unnamed crossfade")
129 , CROSSFADE_DEFAULT_PROPERTIES
130 , _fade_in (Evoral::Parameter(FadeInAutomation
)) // linear (gain coefficient) => -inf..+6dB
131 , _fade_out (Evoral::Parameter(FadeOutAutomation
)) // linear (gain coefficient) => -inf..+6dB
134 boost::shared_ptr
<Region
> r
;
136 LocaleGuard
lg (X_("POSIX"));
138 /* we have to find the in/out regions before we can do anything else */
140 if ((prop
= node
.property ("in")) == 0) {
141 error
<< _("Crossfade: no \"in\" region in state") << endmsg
;
142 throw failed_constructor();
145 PBD::ID
id (prop
->value());
147 if ((r
= playlist
.find_region (id
)) == 0) {
148 error
<< string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id
, playlist
.name())
150 throw failed_constructor();
153 if ((_in
= boost::dynamic_pointer_cast
<AudioRegion
> (r
)) == 0) {
154 throw failed_constructor();
157 if ((prop
= node
.property ("out")) == 0) {
158 error
<< _("Crossfade: no \"out\" region in state") << endmsg
;
159 throw failed_constructor();
162 PBD::ID
id2 (prop
->value());
164 if ((r
= playlist
.find_region (id2
)) == 0) {
165 error
<< string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2
, playlist
.name())
167 throw failed_constructor();
170 if ((_out
= boost::dynamic_pointer_cast
<AudioRegion
> (r
)) == 0) {
171 throw failed_constructor();
178 if (set_state (node
, Stateful::loading_state_version
)) {
179 throw failed_constructor();
183 Crossfade::Crossfade (boost::shared_ptr
<Crossfade
> orig
, boost::shared_ptr
<AudioRegion
> newin
, boost::shared_ptr
<AudioRegion
> newout
)
184 : AudioRegion (boost::dynamic_pointer_cast
<const AudioRegion
> (orig
), 0, true)
185 , CROSSFADE_DEFAULT_PROPERTIES
186 , _fade_in (orig
->_fade_in
)
187 , _fade_out (orig
->_fade_out
)
189 _active
= orig
->_active
;
190 _in_update
= orig
->_in_update
;
191 _anchor_point
= orig
->_anchor_point
;
192 _follow_overlap
= orig
->_follow_overlap
;
193 _fixed
= orig
->_fixed
;
198 // copied from Crossfade::initialize()
201 _out
->suspend_fade_out ();
202 _in
->suspend_fade_in ();
204 overlap_type
= _in
->coverage (_out
->position(), _out
->last_frame());
205 layer_relation
= (int32_t) (_in
->layer() - _out
->layer());
207 // Let's make sure the fade isn't too long
208 set_xfade_length(_length
);
212 Crossfade::~Crossfade ()
217 Crossfade::initialize ()
219 /* merge source lists from regions */
221 _sources
= _in
->sources();
222 _sources
.insert (_sources
.end(), _out
->sources().begin(), _out
->sources().end());
223 _master_sources
= _in
->master_sources();
224 _master_sources
.insert(_master_sources
.end(), _out
->master_sources().begin(), _out
->master_sources().end());
228 _out
->suspend_fade_out ();
229 _in
->suspend_fade_in ();
234 #define EQUAL_POWER_MINUS_3DB
235 #ifdef EQUAL_POWER_MINUS_3DB
237 _fade_out
.add ((_length
* 0.000000), 1.000000);
238 _fade_out
.add ((_length
* 0.166667), 0.948859);
239 _fade_out
.add ((_length
* 0.333333), 0.851507);
240 _fade_out
.add ((_length
* 0.500000), 0.707946);
241 _fade_out
.add ((_length
* 0.666667), 0.518174);
242 _fade_out
.add ((_length
* 0.833333), 0.282192);
243 _fade_out
.add ((_length
* 1.000000), 0.000000);
245 #else // EQUAL_POWER_MINUS_6DB
247 _fade_out
.add ((_length
* 0.000000), 1.000000);
248 _fade_out
.add ((_length
* 0.166667), 0.833033);
249 _fade_out
.add ((_length
* 0.333333), 0.666186);
250 _fade_out
.add ((_length
* 0.500000), 0.499459);
251 _fade_out
.add ((_length
* 0.666667), 0.332853);
252 _fade_out
.add ((_length
* 0.833333), 0.166366);
253 _fade_out
.add ((_length
* 1.000000), 0.000000);
261 #define EQUAL_POWER_MINUS_3DB
262 #ifdef EQUAL_POWER_MINUS_3DB
264 _fade_in
.add ((_length
* 0.000000), 0.000000);
265 _fade_in
.add ((_length
* 0.166667), 0.282192);
266 _fade_in
.add ((_length
* 0.333333), 0.518174);
267 _fade_in
.add ((_length
* 0.500000), 0.707946);
268 _fade_in
.add ((_length
* 0.666667), 0.851507);
269 _fade_in
.add ((_length
* 0.833333), 0.948859);
270 _fade_in
.add ((_length
* 1.000000), 1.000000);
272 #else // EQUAL_POWER_MINUS_SIX_DB
274 _fade_in
.add ((_length
* 0.000000), 0.000000);
275 _fade_in
.add ((_length
* 0.166667), 0.166366);
276 _fade_in
.add ((_length
* 0.333333), 0.332853);
277 _fade_in
.add ((_length
* 0.500000), 0.499459);
278 _fade_in
.add ((_length
* 0.666667), 0.666186);
279 _fade_in
.add ((_length
* 0.833333), 0.833033);
280 _fade_in
.add ((_length
* 1.000000), 1.000000);
286 overlap_type
= _in
->coverage (_out
->position(), _out
->last_frame());
287 layer_relation
= (int32_t) (_in
->layer() - _out
->layer());
291 Crossfade::read_raw_internal (Sample
* buf
, framecnt_t start
, framecnt_t cnt
, int channel
) const
293 Sample
* mixdown
= new Sample
[cnt
];
294 float* gain
= new float[cnt
];
297 ret
= read_at (buf
, mixdown
, gain
, start
, cnt
, channel
, cnt
);
306 Crossfade::read_at (Sample
*buf
, Sample
*mixdown_buffer
,
307 float *gain_buffer
, framepos_t start
, framecnt_t cnt
, uint32_t chan_n
,
308 framecnt_t read_frames
, framecnt_t skip_frames
) const
310 frameoffset_t offset
;
317 if (start
< _position
) {
319 /* handle an initial section of the read area that we do not
323 offset
= _position
- start
;
333 to_write
= min (_length
.val(), (nframes64_t
) cnt
);
337 to_write
= min ((_length
- (start
- _position
)), cnt
);
341 offset
= start
- _position
;
343 /* Prevent data from piling up inthe crossfade buffers when reading a transparent region */
344 if (!(_out
->opaque())) {
345 memset (crossfade_buffer_out
, 0, sizeof (Sample
) * to_write
);
346 } else if (!(_in
->opaque())) {
347 memset (crossfade_buffer_in
, 0, sizeof (Sample
) * to_write
);
350 _out
->read_at (crossfade_buffer_out
, mixdown_buffer
, gain_buffer
, start
, to_write
, chan_n
, read_frames
, skip_frames
);
351 _in
->read_at (crossfade_buffer_in
, mixdown_buffer
, gain_buffer
, start
, to_write
, chan_n
, read_frames
, skip_frames
);
353 float* fiv
= new float[to_write
];
354 float* fov
= new float[to_write
];
356 _fade_in
.curve().get_vector (offset
, offset
+to_write
, fiv
, to_write
);
357 _fade_out
.curve().get_vector (offset
, offset
+to_write
, fov
, to_write
);
359 /* note: although we have not explicitly taken into account the return values
360 from _out->read_at() or _in->read_at(), the length() function does this
361 implicitly. why? because it computes a value based on the in+out regions'
362 position and length, and so we know precisely how much data they could return.
365 for (framecnt_t n
= 0; n
< to_write
; ++n
) {
366 buf
[n
] = (crossfade_buffer_out
[n
] * fov
[n
]) + (crossfade_buffer_in
[n
] * fiv
[n
]);
376 Crossfade::coverage (framepos_t start
, framepos_t end
) const
378 framepos_t my_end
= _position
+ _length
;
380 if ((start
>= _position
) && (end
<= my_end
)) {
381 return OverlapInternal
;
383 if ((end
>= _position
) && (end
<= my_end
)) {
386 if ((start
>= _position
) && (start
<= my_end
)) {
389 if ((_position
>= start
) && (_position
<= end
) && (my_end
<= end
)) {
390 return OverlapExternal
;
396 Crossfade::set_active (bool yn
)
400 PropertyChanged (PropertyChange (Properties::active
));
405 Crossfade::refresh ()
407 /* crossfades must be between non-muted regions */
409 if (_out
->muted() || _in
->muted()) {
410 Invalidated (shared_from_this ());
414 /* Top layer shouldn't be transparent */
416 if (!((layer_relation
> 0 ? _in
: _out
)->opaque())) {
417 Invalidated (shared_from_this());
421 /* layer ordering cannot change */
423 int32_t new_layer_relation
= (int32_t) (_in
->layer() - _out
->layer());
425 if (new_layer_relation
* layer_relation
< 0) { // different sign, layers rotated
426 Invalidated (shared_from_this ());
430 OverlapType ot
= _in
->coverage (_out
->first_frame(), _out
->last_frame());
432 if (ot
== OverlapNone
) {
433 Invalidated (shared_from_this ());
439 if (ot
!= overlap_type
) {
441 if (_follow_overlap
) {
444 compute (_in
, _out
, _session
.config
.get_xfade_model());
447 catch (NoCrossfadeHere
& err
) {
448 Invalidated (shared_from_this ());
455 Invalidated (shared_from_this ());
461 send_signal
= update ();
465 PropertyChange bounds
;
466 bounds
.add (Properties::start
);
467 bounds
.add (Properties::position
);
468 bounds
.add (Properties::length
);
469 PropertyChanged (bounds
); /* EMIT SIGNAL */
482 if (_follow_overlap
) {
483 newlen
= _out
->first_frame() + _out
->length() - _in
->first_frame();
489 Invalidated (shared_from_this ());
495 if ((_follow_overlap
&& newlen
!= _length
) || (_length
> newlen
)) {
497 double factor
= newlen
/ (double) _length
;
499 _fade_out
.x_scale (factor
);
500 _fade_in
.x_scale (factor
);
505 switch (_anchor_point
) {
507 _position
= _in
->first_frame();
511 _position
= _in
->last_frame() - _length
;
515 _position
= _out
->last_frame() - _length
;
522 Crossfade::compute (boost::shared_ptr
<AudioRegion
> a
, boost::shared_ptr
<AudioRegion
> b
, CrossfadeModel model
)
524 boost::shared_ptr
<AudioRegion
> top
;
525 boost::shared_ptr
<AudioRegion
> bottom
;
526 framecnt_t short_xfade_length
;
528 short_xfade_length
= _short_xfade_length
;
530 if (a
->layer() < b
->layer()) {
538 /* first check for matching ends */
540 if (top
->first_frame() == bottom
->first_frame()) {
542 /* Both regions start at the same point */
544 if (top
->last_frame() < bottom
->last_frame()) {
546 /* top ends before bottom, so put an xfade
547 in at the end of top.
550 /* [-------- top ---------- ]
551 * {====== bottom =====================}
557 if (top
->last_frame() < short_xfade_length
) {
560 _position
= top
->last_frame() - short_xfade_length
;
563 _length
= min (short_xfade_length
, top
->length());
564 _follow_overlap
= false;
565 _anchor_point
= EndOfIn
;
570 /* top ends after (or same time) as bottom - no xfade
573 /* [-------- top ------------------------ ]
574 * {====== bottom =====================}
577 throw NoCrossfadeHere();
580 } else if (top
->last_frame() == bottom
->last_frame()) {
582 /* Both regions end at the same point */
584 if (top
->first_frame() > bottom
->first_frame()) {
586 /* top starts after bottom, put an xfade in at the
590 /* [-------- top ---------- ]
591 * {====== bottom =====================}
596 _position
= top
->first_frame();
597 _length
= min (short_xfade_length
, top
->length());
598 _follow_overlap
= false;
599 _anchor_point
= StartOfIn
;
604 /* top starts before bottom - no xfade
607 /* [-------- top ------------------------ ]
608 * {====== bottom =====================}
611 throw NoCrossfadeHere();
616 /* OK, time to do more regular overlapping */
618 OverlapType ot
= top
->coverage (bottom
->first_frame(), bottom
->last_frame());
622 /* should be NOTREACHED as a precondition of creating
623 a new crossfade, but we need to handle it here.
625 throw NoCrossfadeHere();
628 case OverlapInternal
:
629 case OverlapExternal
:
630 /* should be NOTREACHED because of tests above */
631 throw NoCrossfadeHere();
634 case OverlapEnd
: /* top covers start of bottom but ends within it */
636 /* [---- top ------------------------]
637 * { ==== bottom ============ }
642 _anchor_point
= EndOfOut
;
644 if (model
== FullCrossfade
) {
645 _position
= bottom
->first_frame(); // "{"
646 _length
= _out
->first_frame() + _out
->length() - _in
->first_frame();
647 /* leave active alone */
648 _follow_overlap
= true;
650 _length
= min (short_xfade_length
, top
->length());
651 _position
= top
->last_frame() - _length
; // "]" - length
653 _follow_overlap
= false;
658 case OverlapStart
: /* top starts within bottom but covers bottom's end */
660 /* { ==== top ============ }
661 * [---- bottom -------------------]
666 _position
= top
->first_frame();
667 _anchor_point
= StartOfIn
;
669 if (model
== FullCrossfade
) {
670 _length
= _out
->first_frame() + _out
->length() - _in
->first_frame();
671 /* leave active alone */
672 _follow_overlap
= true;
674 _length
= min (short_xfade_length
, top
->length());
676 _follow_overlap
= false;
688 Crossfade::get_state ()
690 XMLNode
* node
= new XMLNode (X_("Crossfade"));
693 LocaleGuard
lg (X_("POSIX"));
695 _out
->id().print (buf
, sizeof (buf
));
696 node
->add_property ("out", buf
);
697 _in
->id().print (buf
, sizeof (buf
));
698 node
->add_property ("in", buf
);
699 node
->add_property ("active", (_active
? "yes" : "no"));
700 node
->add_property ("follow-overlap", (_follow_overlap
? "yes" : "no"));
701 node
->add_property ("fixed", (_fixed
? "yes" : "no"));
702 snprintf (buf
, sizeof(buf
), "%" PRId64
, _length
.val());
703 node
->add_property ("length", buf
);
704 snprintf (buf
, sizeof(buf
), "%" PRIu32
, (uint32_t) _anchor_point
);
705 node
->add_property ("anchor-point", buf
);
706 snprintf (buf
, sizeof(buf
), "%" PRId64
, _position
.val());
707 node
->add_property ("position", buf
);
709 child
= node
->add_child ("FadeIn");
711 for (AutomationList::iterator ii
= _fade_in
.begin(); ii
!= _fade_in
.end(); ++ii
) {
714 pnode
= new XMLNode ("point");
716 snprintf (buf
, sizeof (buf
), "%" PRId64
, (framepos_t
) floor ((*ii
)->when
));
717 pnode
->add_property ("x", buf
);
718 snprintf (buf
, sizeof (buf
), "%.12g", (*ii
)->value
);
719 pnode
->add_property ("y", buf
);
720 child
->add_child_nocopy (*pnode
);
723 child
= node
->add_child ("FadeOut");
725 for (AutomationList::iterator ii
= _fade_out
.begin(); ii
!= _fade_out
.end(); ++ii
) {
728 pnode
= new XMLNode ("point");
730 snprintf (buf
, sizeof (buf
), "%" PRId64
, (framepos_t
) floor ((*ii
)->when
));
731 pnode
->add_property ("x", buf
);
732 snprintf (buf
, sizeof (buf
), "%.12g", (*ii
)->value
);
733 pnode
->add_property ("y", buf
);
734 child
->add_child_nocopy (*pnode
);
741 Crossfade::set_state (const XMLNode
& node
, int /*version*/)
743 XMLNodeConstIterator i
;
744 XMLNodeList children
;
747 const XMLProperty
* prop
;
748 LocaleGuard
lg (X_("POSIX"));
749 PropertyChange what_changed
;
752 if ((prop
= node
.property ("position")) != 0) {
753 sscanf (prop
->value().c_str(), "%" PRId64
, &val
);
754 if (val
!= _position
) {
756 what_changed
.add (Properties::position
);
759 warning
<< _("old-style crossfade information - no position information") << endmsg
;
760 _position
= _in
->first_frame();
763 if ((prop
= node
.property ("active")) != 0) {
764 bool x
= string_is_affirmative (prop
->value());
767 what_changed
.add (Properties::active
);
773 if ((prop
= node
.property ("follow-overlap")) != 0) {
774 _follow_overlap
= string_is_affirmative (prop
->value());
776 _follow_overlap
= false;
779 if ((prop
= node
.property ("fixed")) != 0) {
780 _fixed
= string_is_affirmative (prop
->value());
785 if ((prop
= node
.property ("anchor-point")) != 0) {
786 _anchor_point
= AnchorPoint (atoi ((prop
->value().c_str())));
788 _anchor_point
= StartOfIn
;
791 if ((prop
= node
.property ("length")) != 0) {
793 sscanf (prop
->value().c_str(), "%" PRId64
, &val
);
794 if (val
!= _length
) {
796 what_changed
.add (Properties::length
);
801 /* XXX this branch is legacy code from before
802 the point where we stored xfade lengths.
805 if ((_length
= overlap_length()) == 0) {
806 throw failed_constructor();
810 if ((fi
= find_named_node (node
, "FadeIn")) == 0) {
814 if ((fo
= find_named_node (node
, "FadeOut")) == 0) {
823 children
= fi
->children();
825 for (i
= children
.begin(); i
!= children
.end(); ++i
) {
826 if ((*i
)->name() == "point") {
830 prop
= (*i
)->property ("x");
831 sscanf (prop
->value().c_str(), "%" PRId64
, &x
);
833 prop
= (*i
)->property ("y");
834 sscanf (prop
->value().c_str(), "%f", &y
);
847 children
= fo
->children();
849 for (i
= children
.begin(); i
!= children
.end(); ++i
) {
850 if ((*i
)->name() == "point") {
855 prop
= (*i
)->property ("x");
856 sscanf (prop
->value().c_str(), "%" PRId64
, &x
);
858 prop
= (*i
)->property ("y");
859 sscanf (prop
->value().c_str(), "%f", &y
);
861 _fade_out
.add (x
, y
);
867 PropertyChanged (what_changed
); /* EMIT SIGNAL */
868 FadesChanged (); /* EMIT SIGNAL */
874 Crossfade::can_follow_overlap () const
880 Crossfade::set_follow_overlap (bool yn
)
882 if (yn
== _follow_overlap
|| _fixed
) {
886 _follow_overlap
= yn
;
889 set_xfade_length (_short_xfade_length
);
891 set_xfade_length (_out
->first_frame() + _out
->length() - _in
->first_frame());
894 PropertyChanged (PropertyChange (Properties::follow_overlap
));
898 Crossfade::set_xfade_length (framecnt_t len
)
900 framecnt_t limit
= 0;
902 switch (_anchor_point
) {
904 limit
= _in
->length();
908 limit
= _in
->length();
912 limit
= _out
->length();
917 len
= min (limit
, len
);
919 double factor
= len
/ (double) _length
;
922 _fade_out
.x_scale (factor
);
923 _fade_in
.x_scale (factor
);
928 PropertyChanged (PropertyChange (Properties::length
));
934 Crossfade::overlap_length () const
939 return _out
->first_frame() + _out
->length() - _in
->first_frame();
943 Crossfade::set_short_xfade_length (framecnt_t n
)
945 _short_xfade_length
= n
;