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