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