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