large chunks of code to deal with pre-analysis of audio; transient/perconset data...
[ardour.git] / libs / ardour / audioregion.cc
1 /*
2     Copyright (C) 2000-2001 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 */
19
20 #include <cmath>
21 #include <climits>
22 #include <cfloat>
23 #include <algorithm>
24
25 #include <set>
26
27 #include <sigc++/bind.h>
28 #include <sigc++/class_slot.h>
29
30 #include <glibmm/thread.h>
31
32 #include <pbd/basename.h>
33 #include <pbd/xml++.h>
34 #include <pbd/stacktrace.h>
35 #include <pbd/enumwriter.h>
36 #include <pbd/convert.h>
37
38 #include <ardour/audioregion.h>
39 #include <ardour/session.h>
40 #include <ardour/gain.h>
41 #include <ardour/dB.h>
42 #include <ardour/playlist.h>
43 #include <ardour/audiofilter.h>
44 #include <ardour/audiofilesource.h>
45 #include <ardour/region_factory.h>
46 #include <ardour/transient_detector.h>
47
48 #include "i18n.h"
49 #include <locale.h>
50
51 using namespace std;
52 using namespace ARDOUR;
53 using namespace PBD;
54
55 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
56
57 Change AudioRegion::FadeInChanged         = ARDOUR::new_change();
58 Change AudioRegion::FadeOutChanged        = ARDOUR::new_change();
59 Change AudioRegion::FadeInActiveChanged   = ARDOUR::new_change();
60 Change AudioRegion::FadeOutActiveChanged  = ARDOUR::new_change();
61 Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change();
62 Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change();
63 Change AudioRegion::EnvelopeChanged       = ARDOUR::new_change();
64
65 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length)
66         : Region (start, length, PBD::basename_nosuffix(src->name()), 0,  Region::Flag(Region::DefaultFlags|Region::External)),
67           _fade_in (0.0, 2.0, 1.0, false),
68           _fade_out (0.0, 2.0, 1.0, false),
69           _envelope (0.0, 2.0, 1.0, false)
70 {
71         /* basic AudioRegion constructor */
72
73         sources.push_back (src);
74         master_sources.push_back (src);
75         src->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
76
77         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
78         if (afs) {
79                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
80         }
81
82         _scale_amplitude = 1.0;
83
84         set_default_fades ();
85         set_default_envelope ();
86
87         listen_to_my_curves ();
88         listen_to_my_sources ();
89 }
90
91 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
92         : Region (start, length, name, layer, flags),
93           _fade_in (0.0, 2.0, 1.0, false),
94           _fade_out (0.0, 2.0, 1.0, false),
95           _envelope (0.0, 2.0, 1.0, false)
96 {
97         /* basic AudioRegion constructor */
98
99         sources.push_back (src);
100         master_sources.push_back (src); 
101         src->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
102
103         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
104         if (afs) {
105                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
106         }
107
108         _scale_amplitude = 1.0;
109
110         set_default_fades ();
111         set_default_envelope ();
112
113         listen_to_my_curves ();
114         listen_to_my_sources ();
115 }
116
117 AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags)
118         : Region (start, length, name, layer, flags),
119           _fade_in (0.0, 2.0, 1.0, false),
120           _fade_out (0.0, 2.0, 1.0, false),
121           _envelope (0.0, 2.0, 1.0, false)
122 {
123         /* basic AudioRegion constructor */
124         
125         for (SourceList::const_iterator i=srcs.begin(); i != srcs.end(); ++i) {
126                 sources.push_back (*i);
127                 master_sources.push_back (*i);
128                 (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
129                 
130                 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
131                 if (afs) {
132                         afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
133                 }
134         }
135
136         _scale_amplitude = 1.0;
137
138         set_default_fades ();
139         set_default_envelope ();
140
141         listen_to_my_curves ();
142         listen_to_my_sources ();
143 }
144
145
146 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
147         : Region (other, offset, length, name, layer, flags),
148           _fade_in (other->_fade_in),
149           _fade_out (other->_fade_out),
150           _envelope (other->_envelope, (double) offset, (double) offset + length) 
151 {
152         /* create a new AudioRegion, that is part of an existing one */
153         
154         set<boost::shared_ptr<AudioSource> > unique_srcs;
155
156         for (SourceList::const_iterator i= other->sources.begin(); i != other->sources.end(); ++i) {
157                 sources.push_back (*i);
158                 (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
159
160                 pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
161
162                 result = unique_srcs.insert (*i);
163
164                 if (result.second) {
165                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
166                         if (afs) {
167                                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
168                         }
169                 }
170         }
171
172         for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) {
173                 if (unique_srcs.find (*i) == unique_srcs.end()) {
174                         (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
175                 }
176                 master_sources.push_back (*i);
177
178         }
179
180         /* return to default fades if the existing ones are too long */
181         _fade_in_disabled = 0;
182         _fade_out_disabled = 0;
183
184
185         if (_flags & LeftOfSplit) {
186                 if (_fade_in.back()->when >= _length) {
187                         set_default_fade_in ();
188                 } else {
189                         _fade_in_disabled = other->_fade_in_disabled;
190                 }
191                 set_default_fade_out ();
192                 _flags = Flag (_flags & ~Region::LeftOfSplit);
193         }
194
195         if (_flags & RightOfSplit) {
196                 if (_fade_out.back()->when >= _length) {
197                         set_default_fade_out ();
198                 } else {
199                         _fade_out_disabled = other->_fade_out_disabled;
200                 }
201                 set_default_fade_in ();
202                 _flags = Flag (_flags & ~Region::RightOfSplit);
203         }
204
205         _scale_amplitude = other->_scale_amplitude;
206
207         listen_to_my_curves ();
208         listen_to_my_sources ();
209 }
210
211 AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
212         : Region (other),
213           _fade_in (other->_fade_in),
214           _fade_out (other->_fade_out),
215           _envelope (other->_envelope) 
216 {
217         /* Pure copy constructor */
218
219         set<boost::shared_ptr<AudioSource> > unique_srcs;
220
221         for (SourceList::const_iterator i = other->sources.begin(); i != other->sources.end(); ++i) {
222                 sources.push_back (*i);
223                 (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
224                 pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
225
226                 result = unique_srcs.insert (*i);
227
228                 if (result.second) {
229                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
230                         if (afs) {
231                                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
232                         }
233                 }
234         }
235
236         for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) {
237                 master_sources.push_back (*i);
238                 if (unique_srcs.find (*i) == unique_srcs.end()) {
239                         (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
240                 }
241         }
242
243         _scale_amplitude = other->_scale_amplitude;
244         _envelope = other->_envelope;
245
246         _fade_in_disabled = 0;
247         _fade_out_disabled = 0;
248         
249         listen_to_my_curves ();
250         listen_to_my_sources ();
251 }
252
253 AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
254         : Region (node),
255           _fade_in (0.0, 2.0, 1.0, false),
256           _fade_out (0.0, 2.0, 1.0, false),
257           _envelope (0.0, 2.0, 1.0, false)
258 {
259         sources.push_back (src);
260         master_sources.push_back (src);
261         src->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
262
263         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
264         if (afs) {
265                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
266         }
267
268         set_default_fades ();
269
270         if (set_state (node)) {
271                 throw failed_constructor();
272         }
273
274         listen_to_my_curves ();
275         listen_to_my_sources ();
276 }
277
278 AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
279         : Region (node),
280           _fade_in (0.0, 2.0, 1.0, false),
281           _fade_out (0.0, 2.0, 1.0, false),
282           _envelope (0.0, 2.0, 1.0, false)
283 {
284         set<boost::shared_ptr<AudioSource> > unique_srcs;
285
286         for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
287                 sources.push_back (*i);
288                 (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
289                 pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
290
291                 result = unique_srcs.insert (*i);
292
293                 if (result.second) {
294                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
295                         if (afs) {
296                                 afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
297                         }
298                 }
299         }
300
301         for (SourceList::iterator i = srcs.begin(); i != srcs.end(); ++i) {
302                 master_sources.push_back (*i);
303                 if (unique_srcs.find (*i) == unique_srcs.end()) {
304                         (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted));
305                 }
306         }
307
308         set_default_fades ();
309         _scale_amplitude = 1.0;
310
311         if (set_state (node)) {
312                 throw failed_constructor();
313         }
314
315         listen_to_my_curves ();
316         listen_to_my_sources ();
317 }
318
319 AudioRegion::~AudioRegion ()
320 {
321         boost::shared_ptr<Playlist> pl (playlist());
322
323         if (pl) {
324                 for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
325                         (*i)->remove_playlist (pl);
326                 }
327         }
328
329         notify_callbacks ();
330         GoingAway (); /* EMIT SIGNAL */
331 }
332
333 void
334 AudioRegion::listen_to_my_sources ()
335 {
336         for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
337                 (*i)->AnalysisChanged.connect (mem_fun (*this, &AudioRegion::invalidate_transients));
338         }
339 }
340
341 void
342 AudioRegion::listen_to_my_curves ()
343 {
344         _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
345         _fade_in.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed));
346         _fade_out.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
347 }
348
349 bool
350 AudioRegion::verify_length (nframes_t& len)
351 {
352         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
353
354         if (afs && afs->destructive()) {
355                 return true;
356         }
357
358         nframes_t maxlen = 0;
359
360         for (uint32_t n=0; n < sources.size(); ++n) {
361                 maxlen = max (maxlen, sources[n]->length() - _start);
362         }
363         
364         len = min (len, maxlen);
365         
366         return true;
367 }
368
369 bool
370 AudioRegion::verify_start_and_length (nframes_t new_start, nframes_t& new_length)
371 {
372         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
373
374         if (afs && afs->destructive()) {
375                 return true;
376         }
377
378         nframes_t maxlen = 0;
379
380         for (uint32_t n=0; n < sources.size(); ++n) {
381                 maxlen = max (maxlen, sources[n]->length() - new_start);
382         }
383
384         new_length = min (new_length, maxlen);
385
386         return true;
387 }
388 bool
389 AudioRegion::verify_start (nframes_t pos)
390 {
391         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
392
393         if (afs && afs->destructive()) {
394                 return true;
395         }
396
397         for (uint32_t n=0; n < sources.size(); ++n) {
398                 if (pos > sources[n]->length() - _length) {
399                         return false;
400                 }
401         }
402         return true;
403 }
404
405 bool
406 AudioRegion::verify_start_mutable (nframes_t& new_start)
407 {
408         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
409
410         if (afs && afs->destructive()) {
411                 return true;
412         }
413
414         for (uint32_t n=0; n < sources.size(); ++n) {
415                 if (new_start > sources[n]->length() - _length) {
416                         new_start = sources[n]->length() - _length;
417                 }
418         }
419         return true;
420 }
421 void
422 AudioRegion::set_envelope_active (bool yn)
423 {
424         if (envelope_active() != yn) {
425                 char buf[64];
426                 if (yn) {
427                         snprintf (buf, sizeof (buf), "envelope active");
428                         _flags = Flag (_flags|EnvelopeActive);
429                 } else {
430                         snprintf (buf, sizeof (buf), "envelope off");
431                         _flags = Flag (_flags & ~EnvelopeActive);
432                 }
433                 send_change (EnvelopeActiveChanged);
434         }
435 }
436
437 nframes_t
438 AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nframes_t cnt, uint32_t chan_n, double samples_per_unit) const
439 {
440         if (chan_n >= sources.size()) {
441                 return 0; 
442         }
443
444         if (sources[chan_n]->read_peaks (buf, npeaks, offset, cnt, samples_per_unit)) {
445                 return 0;
446         } else {
447                 if (_scale_amplitude != 1.0) {
448                         for (nframes_t n = 0; n < npeaks; ++n) {
449                                 buf[n].max *= _scale_amplitude;
450                                 buf[n].min *= _scale_amplitude;
451                         }
452                 }
453                 return cnt;
454         }
455 }
456
457 nframes64_t
458 AudioRegion::read (Sample* buf, nframes64_t position, nframes64_t cnt, int channel) const
459 {
460         /* raw read, no fades, no gain, nada */
461         return _read_at (sources, buf, 0, 0, _position + position, cnt, channel, 0, 0, true);
462 }
463
464 nframes_t
465 AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, 
466                       nframes_t cnt, 
467                       uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
468 {
469         /* regular diskstream/butler read complete with fades etc */
470         return _read_at (sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames, false);
471 }
472
473 nframes_t
474 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, 
475                              nframes_t cnt, uint32_t chan_n) const
476 {
477         return _read_at (master_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0);
478 }
479
480 nframes_t
481 AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
482                        nframes_t position, nframes_t cnt, 
483                        uint32_t chan_n, 
484                        nframes_t read_frames, 
485                        nframes_t skip_frames,
486                        bool raw) const
487 {
488         nframes_t internal_offset;
489         nframes_t buf_offset;
490         nframes_t to_read;
491
492         if (muted() && !raw) {
493                 return 0; /* read nothing */
494         }
495
496         /* precondition: caller has verified that we cover the desired section */
497
498         if (position < _position) {
499                 internal_offset = 0;
500                 buf_offset = _position - position;
501                 cnt -= buf_offset;
502         } else {
503                 internal_offset = position - _position;
504                 buf_offset = 0;
505         }
506
507         if (internal_offset >= _length) {
508                 return 0; /* read nothing */
509         }
510
511         if ((to_read = min (cnt, _length - internal_offset)) == 0) {
512                 return 0; /* read nothing */
513         }
514
515         if (opaque() || raw) {
516                 /* overwrite whatever is there */
517                 mixdown_buffer = buf + buf_offset;
518         } else {
519                 mixdown_buffer += buf_offset;
520         }
521
522         if (!raw) {
523                 _read_data_count = 0;
524         }
525
526         if (chan_n < n_channels()) {
527
528                 if (srcs[chan_n]->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
529                         
530                         return 0; /* "read nothing" */
531                 }
532                 
533                 if (!raw) {
534                         _read_data_count += srcs[chan_n]->read_data_count();
535                 }
536
537         } else {
538                 
539                 /* track is N-channel, this region has less channels; silence the ones
540                    we don't have.
541                 */
542
543                 memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
544
545                 /* no fades required */
546
547                 if (!raw) {
548                         goto merge;
549                 }
550         }
551
552         /* fade in */
553
554         if (!raw) {
555         
556                 if (_flags & FadeIn) {
557                         
558                         nframes_t fade_in_length = (nframes_t) _fade_in.back()->when;
559                         
560                         /* see if this read is within the fade in */
561                         
562                         if (internal_offset < fade_in_length) {
563                                 
564                                 nframes_t limit;
565                                 
566                                 limit = min (to_read, fade_in_length - internal_offset);
567                                 
568                                 _fade_in.get_vector (internal_offset, internal_offset+limit, gain_buffer, limit);
569                                 
570                                 for (nframes_t n = 0; n < limit; ++n) {
571                                         mixdown_buffer[n] *= gain_buffer[n];
572                                 }
573                         }
574                 }
575                 
576                 /* fade out */
577                 
578                 if (_flags & FadeOut) {
579                         
580                         /* see if some part of this read is within the fade out */
581                         
582                 /* .................        >|            REGION
583                                             _length
584                                             
585                                  {           }            FADE
586                                              fade_out_length
587                                  ^                                           
588                                _length - fade_out_length
589                         |--------------|
590                         ^internal_offset
591                                        ^internal_offset + to_read
592                                        
593                                        we need the intersection of [internal_offset,internal_offset+to_read] with
594                                        [_length - fade_out_length, _length]
595                                        
596                 */
597
598         
599                         nframes_t fade_out_length = (nframes_t) _fade_out.back()->when;
600                         nframes_t fade_interval_start = max(internal_offset, _length-fade_out_length);
601                         nframes_t fade_interval_end   = min(internal_offset + to_read, _length);
602                         
603                         if (fade_interval_end > fade_interval_start) {
604                                 /* (part of the) the fade out is  in this buffer */
605                                 
606                                 nframes_t limit = fade_interval_end - fade_interval_start;
607                                 nframes_t curve_offset = fade_interval_start - (_length-fade_out_length);
608                                 nframes_t fade_offset = fade_interval_start - internal_offset;
609                                 
610                                 _fade_out.get_vector (curve_offset,curve_offset+limit, gain_buffer, limit);
611                                 
612                                 for (nframes_t n = 0, m = fade_offset; n < limit; ++n, ++m) {
613                                         mixdown_buffer[m] *= gain_buffer[n];
614                                 }
615                         } 
616                         
617                 }
618                 
619                 /* Regular gain curves */
620                 
621                 if (envelope_active())  {
622                         _envelope.get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
623                         
624                         if (_scale_amplitude != 1.0f) {
625                                 for (nframes_t n = 0; n < to_read; ++n) {
626                                         mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
627                                 }
628                         } else {
629                                 for (nframes_t n = 0; n < to_read; ++n) {
630                                         mixdown_buffer[n] *= gain_buffer[n];
631                                 }
632                         }
633                 } else if (_scale_amplitude != 1.0f) {
634                         Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
635                 }
636         
637           merge:
638                 
639                 if (!opaque()) {
640                         
641                         /* gack. the things we do for users.
642                          */
643                         
644                         buf += buf_offset;
645                         
646                         for (nframes_t n = 0; n < to_read; ++n) {
647                                 buf[n] += mixdown_buffer[n];
648                         }
649                 } 
650         }
651
652         return to_read;
653 }
654         
655 XMLNode&
656 AudioRegion::state (bool full)
657 {
658         XMLNode& node (Region::state (full));
659         XMLNode *child;
660         char buf[64];
661         char buf2[64];
662         LocaleGuard lg (X_("POSIX"));
663         
664         node.add_property ("flags", enum_2_string (_flags));
665
666         snprintf (buf, sizeof(buf), "%.12g", _scale_amplitude);
667         node.add_property ("scale-gain", buf);
668
669         for (uint32_t n=0; n < sources.size(); ++n) {
670                 snprintf (buf2, sizeof(buf2), "source-%d", n);
671                 sources[n]->id().print (buf, sizeof (buf));
672                 node.add_property (buf2, buf);
673         }
674
675         snprintf (buf, sizeof (buf), "%u", (uint32_t) sources.size());
676         node.add_property ("channels", buf);
677
678         if (full) {
679         
680                 child = node.add_child (X_("FadeIn"));
681                 
682                 if ((_flags & DefaultFadeIn)) {
683                         child->add_property (X_("default"), X_("yes"));
684                 } else {
685                         child->add_child_nocopy (_fade_in.get_state ());
686                 }
687
688                 child->add_property (X_("active"), _fade_in_disabled ? X_("no") : X_("yes"));
689                 
690                 child = node.add_child (X_("FadeOut"));
691                 
692                 if ((_flags & DefaultFadeOut)) {
693                         child->add_property (X_("default"), X_("yes"));
694                 } else {
695                         child->add_child_nocopy (_fade_out.get_state ());
696                 }
697                 
698                 child->add_property (X_("active"), _fade_out_disabled ? X_("no") : X_("yes"));
699         }
700         
701         child = node.add_child ("Envelope");
702
703         if (full) {
704                 bool default_env = false;
705                 
706                 // If there are only two points, the points are in the start of the region and the end of the region
707                 // so, if they are both at 1.0f, that means the default region.
708
709                 if (_envelope.size() == 2 &&
710                     _envelope.front()->value == 1.0f &&
711                     _envelope.back()->value==1.0f) {
712                         if (_envelope.front()->when == 0 && _envelope.back()->when == _length) {
713                                 default_env = true;
714                         }
715                 } 
716                 
717                 if (default_env) {
718                         child->add_property ("default", "yes");
719                 } else {
720                         child->add_child_nocopy (_envelope.get_state ());
721                 }
722
723         } else {
724                 child->add_property ("default", "yes");
725         }
726
727         for (uint32_t n=0; n < master_sources.size(); ++n) {
728                 snprintf (buf2, sizeof(buf2), "master-source-%d", n);
729                 master_sources[n]->id().print (buf, sizeof (buf));
730                 node.add_property (buf2, buf);
731         }
732
733         if (full && _extra_xml) {
734                 node.add_child_copy (*_extra_xml);
735         }
736
737         return node;
738 }
739
740 int
741 AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool send)
742 {
743         const XMLNodeList& nlist = node.children();
744         const XMLProperty *prop;
745         LocaleGuard lg (X_("POSIX"));
746
747         Region::set_live_state (node, what_changed, false);
748
749         uint32_t old_flags = _flags;
750
751         if ((prop = node.property ("flags")) != 0) {
752                 _flags = Flag (string_2_enum (prop->value(), _flags));
753
754                 //_flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
755
756                 _flags = Flag (_flags & ~Region::LeftOfSplit);
757                 _flags = Flag (_flags & ~Region::RightOfSplit);
758         }
759
760         if ((old_flags ^ _flags) & Muted) {
761                 what_changed = Change (what_changed|MuteChanged);
762         }
763         if ((old_flags ^ _flags) & Opaque) {
764                 what_changed = Change (what_changed|OpacityChanged);
765         }
766         if ((old_flags ^ _flags) & Locked) {
767                 what_changed = Change (what_changed|LockChanged);
768         }
769
770         if ((prop = node.property ("scale-gain")) != 0) {
771                 _scale_amplitude = atof (prop->value().c_str());
772                 what_changed = Change (what_changed|ScaleAmplitudeChanged);
773         } else {
774                 _scale_amplitude = 1.0;
775         }
776         
777         /* Now find envelope description and other misc child items */
778                                 
779         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
780                 
781                 XMLNode *child;
782                 XMLProperty *prop;
783                 
784                 child = (*niter);
785                 
786                 if (child->name() == "Envelope") {
787                         
788                         _envelope.clear ();
789
790                         if ((prop = child->property ("default")) != 0 || _envelope.set_state (*child)) {
791                                 set_default_envelope ();
792                         }
793
794                         _envelope.set_max_xval (_length);
795                         _envelope.truncate_end (_length);
796
797                 } else if (child->name() == "FadeIn") {
798                         
799                         _fade_in.clear ();
800                         
801                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
802                                 set_default_fade_in ();
803                         } else {
804                                 XMLNode* grandchild = child->child ("AutomationList");
805                                 if (grandchild) {
806                                         _fade_in.set_state (*grandchild);
807                                 }
808                         }
809
810                         if ((prop = child->property ("active")) != 0) {
811                                 if (prop->value() == "yes") {
812                                         set_fade_in_active (true);
813                                 } else {
814                                         set_fade_in_active (true);
815                                 }
816                         }
817
818                 } else if (child->name() == "FadeOut") {
819                         
820                         _fade_out.clear ();
821
822                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
823                                 set_default_fade_out ();
824                         } else {
825                                 XMLNode* grandchild = child->child ("AutomationList");
826                                 if (grandchild) {
827                                         _fade_out.set_state (*grandchild);
828                                 } 
829                         }
830
831                         if ((prop = child->property ("active")) != 0) {
832                                 if (prop->value() == "yes") {
833                                         set_fade_out_active (true);
834                                 } else {
835                                         set_fade_out_active (false);
836                                 }
837                         }
838
839                 } 
840         }
841
842         if (send) {
843                 send_change (what_changed);
844         }
845
846         return 0;
847 }
848
849 int
850 AudioRegion::set_state (const XMLNode& node)
851 {
852         /* Region::set_state() calls the virtual set_live_state(),
853            which will get us back to AudioRegion::set_live_state()
854            to handle the relevant stuff.
855         */
856
857         return Region::set_state (node);
858 }
859
860 void
861 AudioRegion::set_fade_in_shape (FadeShape shape)
862 {
863         set_fade_in (shape, (nframes_t) _fade_in.back()->when);
864 }
865
866 void
867 AudioRegion::set_fade_out_shape (FadeShape shape)
868 {
869         set_fade_out (shape, (nframes_t) _fade_out.back()->when);
870 }
871
872 void
873 AudioRegion::set_fade_in (FadeShape shape, nframes_t len)
874 {
875         _fade_in.freeze ();
876         _fade_in.clear ();
877
878         switch (shape) {
879         case Linear:
880                 _fade_in.fast_simple_add (0.0, 0.0);
881                 _fade_in.fast_simple_add (len, 1.0);
882                 break;
883
884         case Fast:
885                 _fade_in.fast_simple_add (0, 0);
886                 _fade_in.fast_simple_add (len * 0.389401, 0.0333333);
887                 _fade_in.fast_simple_add (len * 0.629032, 0.0861111);
888                 _fade_in.fast_simple_add (len * 0.829493, 0.233333);
889                 _fade_in.fast_simple_add (len * 0.9447, 0.483333);
890                 _fade_in.fast_simple_add (len * 0.976959, 0.697222);
891                 _fade_in.fast_simple_add (len, 1);
892                 break;
893
894         case Slow:
895                 _fade_in.fast_simple_add (0, 0);
896                 _fade_in.fast_simple_add (len * 0.0207373, 0.197222);
897                 _fade_in.fast_simple_add (len * 0.0645161, 0.525);
898                 _fade_in.fast_simple_add (len * 0.152074, 0.802778);
899                 _fade_in.fast_simple_add (len * 0.276498, 0.919444);
900                 _fade_in.fast_simple_add (len * 0.481567, 0.980556);
901                 _fade_in.fast_simple_add (len * 0.767281, 1);
902                 _fade_in.fast_simple_add (len, 1);
903                 break;
904
905         case LogA:
906                 _fade_in.fast_simple_add (0, 0);
907                 _fade_in.fast_simple_add (len * 0.0737327, 0.308333);
908                 _fade_in.fast_simple_add (len * 0.246544, 0.658333);
909                 _fade_in.fast_simple_add (len * 0.470046, 0.886111);
910                 _fade_in.fast_simple_add (len * 0.652074, 0.972222);
911                 _fade_in.fast_simple_add (len * 0.771889, 0.988889);
912                 _fade_in.fast_simple_add (len, 1);
913                 break;
914
915         case LogB:
916                 _fade_in.fast_simple_add (0, 0);
917                 _fade_in.fast_simple_add (len * 0.304147, 0.0694444);
918                 _fade_in.fast_simple_add (len * 0.529954, 0.152778);
919                 _fade_in.fast_simple_add (len * 0.725806, 0.333333);
920                 _fade_in.fast_simple_add (len * 0.847926, 0.558333);
921                 _fade_in.fast_simple_add (len * 0.919355, 0.730556);
922                 _fade_in.fast_simple_add (len, 1);
923                 break;
924         }
925
926         _fade_in.thaw ();
927         _fade_in_shape = shape;
928
929         send_change (FadeInChanged);
930 }
931
932 void
933 AudioRegion::set_fade_out (FadeShape shape, nframes_t len)
934 {
935         _fade_out.freeze ();
936         _fade_out.clear ();
937
938         switch (shape) {
939         case Fast:
940                 _fade_out.fast_simple_add (len * 0, 1);
941                 _fade_out.fast_simple_add (len * 0.023041, 0.697222);
942                 _fade_out.fast_simple_add (len * 0.0553,   0.483333);
943                 _fade_out.fast_simple_add (len * 0.170507, 0.233333);
944                 _fade_out.fast_simple_add (len * 0.370968, 0.0861111);
945                 _fade_out.fast_simple_add (len * 0.610599, 0.0333333);
946                 _fade_out.fast_simple_add (len * 1, 0);
947                 break;
948
949         case LogA:
950                 _fade_out.fast_simple_add (len * 0, 1);
951                 _fade_out.fast_simple_add (len * 0.228111, 0.988889);
952                 _fade_out.fast_simple_add (len * 0.347926, 0.972222);
953                 _fade_out.fast_simple_add (len * 0.529954, 0.886111);
954                 _fade_out.fast_simple_add (len * 0.753456, 0.658333);
955                 _fade_out.fast_simple_add (len * 0.9262673, 0.308333);
956                 _fade_out.fast_simple_add (len * 1, 0);
957                 break;
958
959         case Slow:
960                 _fade_out.fast_simple_add (len * 0, 1);
961                 _fade_out.fast_simple_add (len * 0.305556, 1);
962                 _fade_out.fast_simple_add (len * 0.548611, 0.991736);
963                 _fade_out.fast_simple_add (len * 0.759259, 0.931129);
964                 _fade_out.fast_simple_add (len * 0.918981, 0.68595);
965                 _fade_out.fast_simple_add (len * 0.976852, 0.22865);
966                 _fade_out.fast_simple_add (len * 1, 0);
967                 break;
968
969         case LogB:
970                 _fade_out.fast_simple_add (len * 0, 1);
971                 _fade_out.fast_simple_add (len * 0.080645, 0.730556);
972                 _fade_out.fast_simple_add (len * 0.277778, 0.289256);
973                 _fade_out.fast_simple_add (len * 0.470046, 0.152778);
974                 _fade_out.fast_simple_add (len * 0.695853, 0.0694444);
975                 _fade_out.fast_simple_add (len * 1, 0);
976                 break;
977
978         case Linear:
979                 _fade_out.fast_simple_add (len * 0, 1);
980                 _fade_out.fast_simple_add (len * 1, 0);
981                 break;
982         }
983
984         _fade_out.thaw ();
985         _fade_out_shape = shape;
986
987         send_change (FadeOutChanged);
988 }
989
990 void
991 AudioRegion::set_fade_in_length (nframes_t len)
992 {
993         if (len > _length) {
994                 len = _length - 1;
995         }
996
997         bool changed = _fade_in.extend_to (len);
998
999         if (changed) {
1000                 _flags = Flag (_flags & ~DefaultFadeIn);
1001                 send_change (FadeInChanged);
1002         }
1003 }
1004
1005 void
1006 AudioRegion::set_fade_out_length (nframes_t len)
1007 {
1008         if (len > _length) {
1009                 len = _length - 1;
1010         }
1011
1012         bool changed =  _fade_out.extend_to (len);
1013
1014         if (changed) {
1015                 _flags = Flag (_flags & ~DefaultFadeOut);
1016                 send_change (FadeOutChanged);
1017         }
1018 }
1019
1020 void
1021 AudioRegion::set_fade_in_active (bool yn)
1022 {
1023         if (yn == (_flags & FadeIn)) {
1024                 return;
1025         }
1026         if (yn) {
1027                 _flags = Flag (_flags|FadeIn);
1028         } else {
1029                 _flags = Flag (_flags & ~FadeIn);
1030         }
1031
1032         send_change (FadeInActiveChanged);
1033 }
1034
1035 void
1036 AudioRegion::set_fade_out_active (bool yn)
1037 {
1038         if (yn == (_flags & FadeOut)) {
1039                 return;
1040         }
1041         if (yn) {
1042                 _flags = Flag (_flags | FadeOut);
1043         } else {
1044                 _flags = Flag (_flags & ~FadeOut);
1045         }
1046
1047         send_change (FadeOutActiveChanged);
1048 }
1049
1050 bool
1051 AudioRegion::fade_in_is_default () const
1052 {
1053         return _fade_in_shape == Linear && _fade_in.back()->when == 64;
1054 }
1055
1056 bool
1057 AudioRegion::fade_out_is_default () const
1058 {
1059         return _fade_out_shape == Linear && _fade_out.back()->when == 64;
1060 }
1061
1062 void
1063 AudioRegion::set_default_fade_in ()
1064 {
1065         set_fade_in (Linear, 64);
1066 }
1067
1068 void
1069 AudioRegion::set_default_fade_out ()
1070 {
1071         set_fade_out (Linear, 64);
1072 }
1073
1074 void
1075 AudioRegion::set_default_fades ()
1076 {
1077         _fade_in_disabled = 0;
1078         _fade_out_disabled = 0;
1079         set_default_fade_in ();
1080         set_default_fade_out ();
1081 }
1082
1083 void
1084 AudioRegion::set_default_envelope ()
1085 {
1086         _envelope.freeze ();
1087         _envelope.clear ();
1088         _envelope.fast_simple_add (0, 1.0f);
1089         _envelope.fast_simple_add (_length, 1.0f);
1090         _envelope.thaw ();
1091 }
1092
1093 void
1094 AudioRegion::recompute_at_end ()
1095 {
1096         /* our length has changed. recompute a new final point by interpolating 
1097            based on the the existing curve.
1098         */
1099         
1100         _envelope.freeze ();
1101         _envelope.truncate_end (_length);
1102         _envelope.set_max_xval (_length);
1103         _envelope.thaw ();
1104
1105         if (_fade_in.back()->when > _length) {
1106                 _fade_in.extend_to (_length);
1107                 send_change (FadeInChanged);
1108         }
1109
1110         if (_fade_out.back()->when > _length) {
1111                 _fade_out.extend_to (_length);
1112                 send_change (FadeOutChanged);
1113         }
1114 }       
1115
1116 void
1117 AudioRegion::recompute_at_start ()
1118 {
1119         /* as above, but the shift was from the front */
1120
1121         _envelope.truncate_start (_length);
1122
1123         if (_fade_in.back()->when > _length) {
1124                 _fade_in.extend_to (_length);
1125                 send_change (FadeInChanged);
1126         }
1127
1128         if (_fade_out.back()->when > _length) {
1129                 _fade_out.extend_to (_length);
1130                 send_change (FadeOutChanged);
1131         }
1132 }
1133
1134 int
1135 AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<AudioRegion> >& v) const
1136 {
1137         SourceList srcs;
1138         string new_name;
1139         int n;
1140
1141         if (sources.size() < 2) {
1142                 return 0;
1143         }
1144
1145         n = 0;
1146
1147         for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
1148
1149                 srcs.clear ();
1150                 srcs.push_back (*i);
1151
1152                 new_name = _name;
1153
1154                 if (sources.size() == 2) {
1155                         if (n == 0) {
1156                                 new_name += "-L";
1157                         } else {
1158                                 new_name += "-R";
1159                         }
1160                 } else {
1161                         new_name += '-';
1162                         new_name += ('0' + n + 1);
1163                 }
1164
1165                 /* create a copy with just one source. prevent if from being thought of as "whole file" even if 
1166                    it covers the entire source file(s).
1167                  */
1168
1169                 Flag f = Flag (_flags & ~WholeFile);
1170
1171                 boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, f);
1172                 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
1173
1174                 v.push_back (ar);
1175                 
1176                 ++n;
1177         }
1178
1179         return 0;
1180 }
1181
1182 void
1183 AudioRegion::source_deleted ()
1184 {
1185         sources.clear ();
1186         drop_references ();
1187 }
1188
1189 vector<string>
1190 AudioRegion::master_source_names ()
1191 {
1192         SourceList::iterator i;
1193
1194         vector<string> names;
1195         for (i = master_sources.begin(); i != master_sources.end(); ++i) {
1196                 names.push_back((*i)->name());
1197         }
1198
1199         return names;
1200 }
1201
1202 void
1203 AudioRegion::set_master_sources (SourceList& srcs)
1204 {
1205         master_sources = srcs;
1206 }
1207
1208 bool
1209 AudioRegion::source_equivalent (boost::shared_ptr<const Region> o) const
1210 {
1211         boost::shared_ptr<const AudioRegion> other = boost::dynamic_pointer_cast<const AudioRegion>(o);
1212
1213         if (!other)
1214                 return false;
1215
1216         SourceList::const_iterator i;
1217         SourceList::const_iterator io;
1218
1219         for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) {
1220                 if ((*i)->id() != (*io)->id()) {
1221                         return false;
1222                 }
1223         }
1224
1225         for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) {
1226                 if ((*i)->id() != (*io)->id()) {
1227                         return false;
1228                 }
1229         }
1230
1231         return true;
1232 }
1233
1234 int
1235 AudioRegion::apply (AudioFilter& filter)
1236 {
1237         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (shared_from_this());
1238         return filter.run (ar);
1239 }
1240
1241 int
1242 AudioRegion::exportme (Session& session, AudioExportSpecification& spec)
1243 {
1244         const nframes_t blocksize = 4096;
1245         nframes_t to_read;
1246         int status = -1;
1247
1248         spec.channels = sources.size();
1249
1250         if (spec.prepare (blocksize, session.frame_rate())) {
1251                 goto out;
1252         }
1253
1254         spec.pos = 0;
1255         spec.total_frames = _length;
1256
1257         while (spec.pos < _length && !spec.stop) {
1258                 
1259                 
1260                 /* step 1: interleave */
1261                 
1262                 to_read = min (_length - spec.pos, blocksize);
1263                 
1264                 if (spec.channels == 1) {
1265
1266                         if (sources.front()->read (spec.dataF, _start + spec.pos, to_read) != to_read) {
1267                                 goto out;
1268                         }
1269
1270                 } else {
1271
1272                         Sample buf[blocksize];
1273
1274                         for (uint32_t chan = 0; chan < spec.channels; ++chan) {
1275                                 
1276                                 if (sources[chan]->read (buf, _start + spec.pos, to_read) != to_read) {
1277                                         goto out;
1278                                 }
1279                                 
1280                                 for (nframes_t x = 0; x < to_read; ++x) {
1281                                         spec.dataF[chan+(x*spec.channels)] = buf[x];
1282                                 }
1283                         }
1284                 }
1285                 
1286                 if (spec.process (to_read)) {
1287                         goto out;
1288                 }
1289                 
1290                 spec.pos += to_read;
1291                 spec.progress = (double) spec.pos /_length;
1292                 
1293         }
1294         
1295         status = 0;
1296
1297   out:  
1298         spec.running = false;
1299         spec.status = status;
1300         spec.clear();
1301         
1302         return status;
1303 }
1304
1305 boost::shared_ptr<Region>
1306 AudioRegion::get_parent() const
1307 {
1308         boost::shared_ptr<Playlist> pl (playlist());
1309
1310         if (pl) {
1311                 boost::shared_ptr<AudioRegion> ar;
1312                 boost::shared_ptr<AudioRegion const> grrr2 = boost::dynamic_pointer_cast<AudioRegion const> (shared_from_this());
1313                 
1314                 if (grrr2 && (ar = pl->session().find_whole_file_parent (grrr2))) {
1315                         return boost::static_pointer_cast<Region> (ar);
1316                 }
1317         }
1318         
1319         return boost::shared_ptr<Region>();
1320 }
1321
1322 void
1323 AudioRegion::set_scale_amplitude (gain_t g)
1324 {
1325         boost::shared_ptr<Playlist> pl (playlist());
1326
1327         _scale_amplitude = g;
1328
1329         /* tell the diskstream we're in */
1330         
1331         if (pl) {
1332                 pl->Modified();
1333         }
1334
1335         /* tell everybody else */
1336
1337         send_change (ScaleAmplitudeChanged);
1338 }
1339
1340 void
1341 AudioRegion::normalize_to (float target_dB)
1342 {
1343         const nframes_t blocksize = 64 * 1024;
1344         Sample buf[blocksize];
1345         nframes_t fpos;
1346         nframes_t fend;
1347         nframes_t to_read;
1348         double maxamp = 0;
1349         gain_t target = dB_to_coefficient (target_dB);
1350
1351         if (target == 1.0f) {
1352                 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1353                    that we may have clipped.
1354                 */
1355                 target -= FLT_EPSILON;
1356         }
1357
1358         fpos = _start;
1359         fend = _start + _length;
1360
1361         /* first pass: find max amplitude */
1362
1363         while (fpos < fend) {
1364
1365                 uint32_t n;
1366
1367                 to_read = min (fend - fpos, blocksize);
1368
1369                 for (n = 0; n < n_channels(); ++n) {
1370
1371                         /* read it in */
1372
1373                         if (source (n)->read (buf, fpos, to_read) != to_read) {
1374                                 return;
1375                         }
1376                         
1377                         maxamp = Session::compute_peak (buf, to_read, maxamp);
1378                 }
1379
1380                 fpos += to_read;
1381         };
1382
1383         if (maxamp == 0.0f) {
1384                 /* don't even try */
1385                 return;
1386         }
1387
1388         if (maxamp == target) {
1389                 /* we can't do anything useful */
1390                 return;
1391         }
1392
1393         /* compute scale factor */
1394
1395         _scale_amplitude = target/maxamp;
1396
1397         /* tell the diskstream we're in */
1398
1399         boost::shared_ptr<Playlist> pl (playlist());
1400
1401         if (pl) {
1402                 pl->Modified();
1403         }
1404
1405         /* tell everybody else */
1406
1407         send_change (ScaleAmplitudeChanged);
1408 }
1409
1410 void
1411 AudioRegion::fade_in_changed ()
1412 {
1413         send_change (FadeInChanged);
1414 }
1415
1416 void
1417 AudioRegion::fade_out_changed ()
1418 {
1419         send_change (FadeOutChanged);
1420 }
1421
1422 void
1423 AudioRegion::envelope_changed ()
1424 {
1425         send_change (EnvelopeChanged);
1426 }
1427
1428 void
1429 AudioRegion::suspend_fade_in ()
1430 {
1431         if (++_fade_in_disabled == 1) {
1432                 if (fade_in_is_default()) {
1433                         set_fade_in_active (false);
1434                 }
1435         }
1436 }
1437
1438 void
1439 AudioRegion::resume_fade_in ()
1440 {
1441         if (--_fade_in_disabled == 0 && _fade_in_disabled) {
1442                 set_fade_in_active (true);
1443         }
1444 }
1445
1446 void
1447 AudioRegion::suspend_fade_out ()
1448 {
1449         if (++_fade_out_disabled == 1) {
1450                 if (fade_out_is_default()) {
1451                         set_fade_out_active (false);
1452                 }
1453         }
1454 }
1455
1456 void
1457 AudioRegion::resume_fade_out ()
1458 {
1459         if (--_fade_out_disabled == 0 &&_fade_out_disabled) {
1460                 set_fade_out_active (true);
1461         }
1462 }
1463
1464 bool
1465 AudioRegion::speed_mismatch (float sr) const
1466 {
1467         if (sources.empty()) {
1468                 /* impossible, but ... */
1469                 return false;
1470         }
1471
1472         float fsr = sources.front()->sample_rate();
1473
1474         return fsr != sr;
1475 }
1476
1477 void
1478 AudioRegion::source_offset_changed ()
1479 {
1480         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(sources.front());
1481
1482         if (afs && afs->destructive()) {
1483                 // set_start (source()->natural_position(), this);
1484                 set_position (source()->natural_position(), this);
1485         } 
1486 }
1487
1488 void
1489 AudioRegion::set_playlist (boost::weak_ptr<Playlist> wpl)
1490 {
1491         boost::shared_ptr<Playlist> old_playlist = (_playlist.lock());
1492
1493         boost::shared_ptr<Playlist> pl (wpl.lock());
1494
1495         if (old_playlist == pl) {
1496                 return;
1497         }
1498
1499         Region::set_playlist (wpl);
1500
1501         if (pl) {
1502                 if (old_playlist) {
1503                         for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
1504                                 (*i)->remove_playlist (_playlist);      
1505                                 (*i)->add_playlist (pl);
1506                         }
1507                 } else {
1508                         for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
1509                                 (*i)->add_playlist (pl);
1510                         }
1511                 }
1512         } else {
1513                 if (old_playlist) {
1514                         for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) {
1515                                 (*i)->remove_playlist (old_playlist);
1516                         }
1517                 }
1518         }
1519 }
1520
1521 int
1522 AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
1523 {
1524         boost::shared_ptr<Playlist> pl = playlist();
1525
1526         if (!pl) {
1527                 return -1;
1528         }
1529
1530         if (valid_transients && !force_new) {
1531                 results = _transients;
1532                 return 0;
1533         }
1534
1535         SourceList::iterator s;
1536         
1537         for (s = sources.begin() ; s != sources.end(); ++s) {
1538                 if (!(*s)->has_been_analysed()) {
1539                         cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
1540                         break;
1541                 }
1542         }
1543         
1544         if (s == sources.end()) {
1545                 /* all sources are analyzed, merge data from each one */
1546
1547                 for (s = sources.begin() ; s != sources.end(); ++s) {
1548
1549                         /* find the set of transients within the bounds of this region */
1550
1551                         AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
1552                                                                          (*s)->transients.end(),
1553                                                                          _start);
1554
1555                         AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
1556                                                                           (*s)->transients.end(),
1557                                                                           _start + _length);
1558                                                                          
1559                         /* and add them */
1560
1561                         results.insert (results.end(), low, high);
1562                 }
1563
1564                 TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1565                 
1566                 /* translate all transients to current position */
1567
1568                 for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
1569                         (*x) -= _start;
1570                         (*x) += _position;
1571                 }
1572
1573                 _transients = results;
1574                 valid_transients = true;
1575
1576                 return 0;
1577         }
1578
1579         TransientDetector t (pl->session().frame_rate());
1580         bool existing_results = !results.empty();
1581
1582         _transients.clear ();
1583         valid_transients = false;
1584
1585         for (uint32_t i = 0; i < n_channels(); ++i) {
1586
1587                 AnalysisFeatureList these_results;
1588
1589                 t.reset ();
1590
1591                 if (t.run ("", this, i, these_results)) {
1592                         return -1;
1593                 }
1594
1595                 /* translate all transients to give absolute position */
1596                 
1597                 for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
1598                         (*i) += _position;
1599                 }
1600
1601                 /* merge */
1602                 
1603                 _transients.insert (_transients.end(), these_results.begin(), these_results.end());
1604         }
1605         
1606         if (!results.empty()) {
1607                 if (existing_results) {
1608                         
1609                         /* merge our transients into the existing ones, then clean up
1610                            those.
1611                         */
1612
1613                         results.insert (results.end(), _transients.begin(), _transients.end());
1614                         TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1615                 }
1616
1617                 /* make sure ours are clean too */
1618
1619                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1620         }
1621
1622         valid_transients = true;
1623
1624         return 0;
1625 }
1626
1627 extern "C" {
1628
1629         int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit) 
1630 {
1631         return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (nframes_t) npeaks, (nframes_t) start, (nframes_t) cnt, n_chan,samples_per_unit);
1632 }
1633
1634 uint32_t region_length_from_c (void *arg)
1635 {
1636
1637         return ((AudioRegion *) arg)->length();
1638 }
1639
1640 uint32_t sourcefile_length_from_c (void *arg, double zoom_factor)
1641 {
1642         return ( (AudioRegion *) arg)->source()->available_peaks (zoom_factor) ;
1643 }
1644
1645 } /* extern "C" */