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