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