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