give MackieControlProtocol its own thread and make it parse incoming MIDI in that...
[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->truncate_end (_length);
672
673
674                 } else if (child->name() == "FadeIn") {
675
676                         _fade_in->clear ();
677
678                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
679                                 set_default_fade_in ();
680                         } else {
681                                 XMLNode* grandchild = child->child ("AutomationList");
682                                 if (grandchild) {
683                                         _fade_in->set_state (*grandchild, version);
684                                 }
685                         }
686
687                         if ((prop = child->property ("active")) != 0) {
688                                 if (string_is_affirmative (prop->value())) {
689                                         set_fade_in_active (true);
690                                 } else {
691                                         set_fade_in_active (false);
692                                 }
693                         }
694
695                 } else if (child->name() == "FadeOut") {
696
697                         _fade_out->clear ();
698
699                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
700                                 set_default_fade_out ();
701                         } else {
702                                 XMLNode* grandchild = child->child ("AutomationList");
703                                 if (grandchild) {
704                                         _fade_out->set_state (*grandchild, version);
705                                 }
706                         }
707
708                         if ((prop = child->property ("active")) != 0) {
709                                 if (string_is_affirmative (prop->value())) {
710                                         set_fade_out_active (true);
711                                 } else {
712                                         set_fade_out_active (false);
713                                 }
714                         }
715
716                 }
717         }
718
719         _envelope->thaw ();
720         resume_property_changes ();
721
722         if (send) {
723                 send_change (what_changed);
724         }
725
726         if (the_playlist) {
727                 the_playlist->thaw ();
728         }
729
730         return 0;
731 }
732
733 int
734 AudioRegion::set_state (const XMLNode& node, int version)
735 {
736         PropertyChange what_changed;
737         return _set_state (node, version, what_changed, true);
738 }
739
740 void
741 AudioRegion::set_fade_in_shape (FadeShape shape)
742 {
743         set_fade_in (shape, (framecnt_t) _fade_in->back()->when);
744 }
745
746 void
747 AudioRegion::set_fade_out_shape (FadeShape shape)
748 {
749         set_fade_out (shape, (framecnt_t) _fade_out->back()->when);
750 }
751
752 void
753 AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
754 {
755         _fade_in->freeze ();
756         *_fade_in = *f;
757         _fade_in->thaw ();
758
759         send_change (PropertyChange (Properties::fade_in));
760 }
761
762 void
763 AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
764 {
765         _fade_in->freeze ();
766         _fade_in->clear ();
767
768         switch (shape) {
769         case FadeLinear:
770                 _fade_in->fast_simple_add (0.0, 0.0);
771                 _fade_in->fast_simple_add (len, 1.0);
772                 break;
773
774         case FadeFast:
775                 _fade_in->fast_simple_add (0, 0);
776                 _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
777                 _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
778                 _fade_in->fast_simple_add (len * 0.829493, 0.233333);
779                 _fade_in->fast_simple_add (len * 0.9447, 0.483333);
780                 _fade_in->fast_simple_add (len * 0.976959, 0.697222);
781                 _fade_in->fast_simple_add (len, 1);
782                 break;
783
784         case FadeSlow:
785                 _fade_in->fast_simple_add (0, 0);
786                 _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
787                 _fade_in->fast_simple_add (len * 0.0645161, 0.525);
788                 _fade_in->fast_simple_add (len * 0.152074, 0.802778);
789                 _fade_in->fast_simple_add (len * 0.276498, 0.919444);
790                 _fade_in->fast_simple_add (len * 0.481567, 0.980556);
791                 _fade_in->fast_simple_add (len * 0.767281, 1);
792                 _fade_in->fast_simple_add (len, 1);
793                 break;
794
795         case FadeLogA:
796                 _fade_in->fast_simple_add (0, 0);
797                 _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
798                 _fade_in->fast_simple_add (len * 0.246544, 0.658333);
799                 _fade_in->fast_simple_add (len * 0.470046, 0.886111);
800                 _fade_in->fast_simple_add (len * 0.652074, 0.972222);
801                 _fade_in->fast_simple_add (len * 0.771889, 0.988889);
802                 _fade_in->fast_simple_add (len, 1);
803                 break;
804
805         case FadeLogB:
806                 _fade_in->fast_simple_add (0, 0);
807                 _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
808                 _fade_in->fast_simple_add (len * 0.529954, 0.152778);
809                 _fade_in->fast_simple_add (len * 0.725806, 0.333333);
810                 _fade_in->fast_simple_add (len * 0.847926, 0.558333);
811                 _fade_in->fast_simple_add (len * 0.919355, 0.730556);
812                 _fade_in->fast_simple_add (len, 1);
813                 break;
814         }
815
816         _fade_in->thaw ();
817         send_change (PropertyChange (Properties::fade_in));
818 }
819
820 void
821 AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
822 {
823         _fade_out->freeze ();
824         *_fade_out = *f;
825         _fade_out->thaw ();
826
827         send_change (PropertyChange (Properties::fade_in));
828 }
829
830 void
831 AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
832 {
833         _fade_out->freeze ();
834         _fade_out->clear ();
835
836         switch (shape) {
837         case FadeFast:
838                 _fade_out->fast_simple_add (len * 0, 1);
839                 _fade_out->fast_simple_add (len * 0.023041, 0.697222);
840                 _fade_out->fast_simple_add (len * 0.0553,   0.483333);
841                 _fade_out->fast_simple_add (len * 0.170507, 0.233333);
842                 _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
843                 _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
844                 _fade_out->fast_simple_add (len * 1, 0);
845                 break;
846
847         case FadeLogA:
848                 _fade_out->fast_simple_add (len * 0, 1);
849                 _fade_out->fast_simple_add (len * 0.228111, 0.988889);
850                 _fade_out->fast_simple_add (len * 0.347926, 0.972222);
851                 _fade_out->fast_simple_add (len * 0.529954, 0.886111);
852                 _fade_out->fast_simple_add (len * 0.753456, 0.658333);
853                 _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
854                 _fade_out->fast_simple_add (len * 1, 0);
855                 break;
856
857         case FadeSlow:
858                 _fade_out->fast_simple_add (len * 0, 1);
859                 _fade_out->fast_simple_add (len * 0.305556, 1);
860                 _fade_out->fast_simple_add (len * 0.548611, 0.991736);
861                 _fade_out->fast_simple_add (len * 0.759259, 0.931129);
862                 _fade_out->fast_simple_add (len * 0.918981, 0.68595);
863                 _fade_out->fast_simple_add (len * 0.976852, 0.22865);
864                 _fade_out->fast_simple_add (len * 1, 0);
865                 break;
866
867         case FadeLogB:
868                 _fade_out->fast_simple_add (len * 0, 1);
869                 _fade_out->fast_simple_add (len * 0.080645, 0.730556);
870                 _fade_out->fast_simple_add (len * 0.277778, 0.289256);
871                 _fade_out->fast_simple_add (len * 0.470046, 0.152778);
872                 _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
873                 _fade_out->fast_simple_add (len * 1, 0);
874                 break;
875
876         case FadeLinear:
877                 _fade_out->fast_simple_add (len * 0, 1);
878                 _fade_out->fast_simple_add (len * 1, 0);
879                 break;
880         }
881
882         _fade_out->thaw ();
883         send_change (PropertyChange (Properties::fade_in));
884 }
885
886 void
887 AudioRegion::set_fade_in_length (framecnt_t len)
888 {
889         if (len > _length) {
890                 len = _length - 1;
891         }
892
893         bool changed = _fade_in->extend_to (len);
894
895         if (changed) {
896                 _default_fade_in = false;
897                 send_change (PropertyChange (Properties::fade_in));
898         }
899 }
900
901 void
902 AudioRegion::set_fade_out_length (framecnt_t len)
903 {
904         if (len > _length) {
905                 len = _length - 1;
906         }
907
908         bool changed =  _fade_out->extend_to (len);
909
910         if (changed) {
911                 _default_fade_out = false;
912                 send_change (PropertyChange (Properties::fade_out));
913         }
914 }
915
916 void
917 AudioRegion::set_fade_in_active (bool yn)
918 {
919         if (yn == _fade_in_active) {
920                 return;
921         }
922
923         _fade_in_active = yn;
924         send_change (PropertyChange (Properties::fade_in_active));
925 }
926
927 void
928 AudioRegion::set_fade_out_active (bool yn)
929 {
930         if (yn == _fade_out_active) {
931                 return;
932         }
933         _fade_out_active = yn;
934         send_change (PropertyChange (Properties::fade_out_active));
935 }
936
937 bool
938 AudioRegion::fade_in_is_default () const
939 {
940         return _fade_in->size() == 2 && _fade_in->front()->when == 0 && _fade_in->back()->when == 64;
941 }
942
943 bool
944 AudioRegion::fade_out_is_default () const
945 {
946         return _fade_out->size() == 2 && _fade_out->front()->when == 0 && _fade_out->back()->when == 64;
947 }
948
949 void
950 AudioRegion::set_default_fade_in ()
951 {
952         _fade_in_suspended = 0;
953         set_fade_in (FadeLinear, 64);
954 }
955
956 void
957 AudioRegion::set_default_fade_out ()
958 {
959         _fade_out_suspended = 0;
960         set_fade_out (FadeLinear, 64);
961 }
962
963 void
964 AudioRegion::set_default_fades ()
965 {
966         set_default_fade_in ();
967         set_default_fade_out ();
968 }
969
970 void
971 AudioRegion::set_default_envelope ()
972 {
973         _envelope->freeze ();
974         _envelope->clear ();
975         _envelope->fast_simple_add (0, 1.0f);
976         _envelope->fast_simple_add (_length, 1.0f);
977         _envelope->thaw ();
978 }
979
980 void
981 AudioRegion::recompute_at_end ()
982 {
983         /* our length has changed. recompute a new final point by interpolating
984            based on the the existing curve.
985         */
986
987         _envelope->freeze ();
988         _envelope->truncate_end (_length);
989         _envelope->thaw ();
990
991         suspend_property_changes();
992
993         if (_left_of_split) {
994                 set_default_fade_out ();
995                 _left_of_split = false;
996         } else if (_fade_out->back()->when > _length) {
997                 _fade_out->extend_to (_length);
998                 send_change (PropertyChange (Properties::fade_out));
999         }
1000
1001         if (_fade_in->back()->when > _length) {
1002                 _fade_in->extend_to (_length);
1003                 send_change (PropertyChange (Properties::fade_in));
1004         }
1005
1006         resume_property_changes();
1007 }
1008
1009 void
1010 AudioRegion::recompute_at_start ()
1011 {
1012         /* as above, but the shift was from the front */
1013
1014         _envelope->truncate_start (_length);
1015
1016         suspend_property_changes();
1017
1018         if (_right_of_split) {
1019                 set_default_fade_in ();
1020                 _right_of_split = false;
1021         } else if (_fade_in->back()->when > _length) {
1022                 _fade_in->extend_to (_length);
1023                 send_change (PropertyChange (Properties::fade_in));
1024         }
1025
1026         if (_fade_out->back()->when > _length) {
1027                 _fade_out->extend_to (_length);
1028                 send_change (PropertyChange (Properties::fade_out));
1029         }
1030
1031         resume_property_changes();
1032 }
1033
1034 int
1035 AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr<Region> >& v) const
1036 {
1037         SourceList srcs;
1038         string new_name;
1039         int n = 0;
1040
1041         if (_sources.size() < 2) {
1042                 return 0;
1043         }
1044
1045         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
1046                 srcs.clear ();
1047                 srcs.push_back (*i);
1048
1049                 new_name = _name;
1050
1051                 if (_sources.size() == 2) {
1052                         if (n == 0) {
1053                                 new_name += "-L";
1054                         } else {
1055                                 new_name += "-R";
1056                         }
1057                 } else {
1058                         new_name += '-';
1059                         new_name += ('0' + n + 1);
1060                 }
1061
1062                 /* create a copy with just one source. prevent if from being thought of as
1063                    "whole file" even if it covers the entire source file(s).
1064                  */
1065
1066                 PropertyList plist;
1067
1068                 plist.add (Properties::start, _start.val());
1069                 plist.add (Properties::length, _length.val());
1070                 plist.add (Properties::name, new_name);
1071                 plist.add (Properties::layer, layer ());
1072
1073                 v.push_back(RegionFactory::create (srcs, plist));
1074                 v.back()->set_whole_file (false);
1075
1076                 ++n;
1077         }
1078
1079         return 0;
1080 }
1081
1082 framecnt_t
1083 AudioRegion::read_raw_internal (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
1084 {
1085         return audio_source(channel)->read (buf, pos, cnt);
1086 }
1087
1088 void
1089 AudioRegion::set_scale_amplitude (gain_t g)
1090 {
1091         boost::shared_ptr<Playlist> pl (playlist());
1092
1093         _scale_amplitude = g;
1094
1095         /* tell the diskstream we're in */
1096
1097         if (pl) {
1098                 pl->ContentsChanged();
1099         }
1100
1101         /* tell everybody else */
1102
1103         send_change (PropertyChange (Properties::scale_amplitude));
1104 }
1105
1106 /** @return the maximum (linear) amplitude of the region, or a -ve
1107  *  number if the Progress object reports that the process was cancelled.
1108  */
1109 double
1110 AudioRegion::maximum_amplitude (Progress* p) const
1111 {
1112         framepos_t fpos = _start;
1113         framepos_t const fend = _start + _length;
1114         double maxamp = 0;
1115
1116         framecnt_t const blocksize = 64 * 1024;
1117         Sample buf[blocksize];
1118
1119         while (fpos < fend) {
1120
1121                 uint32_t n;
1122
1123                 framecnt_t const to_read = min (fend - fpos, blocksize);
1124
1125                 for (n = 0; n < n_channels(); ++n) {
1126
1127                         /* read it in */
1128
1129                         if (read_raw_internal (buf, fpos, to_read, n) != to_read) {
1130                                 return 0;
1131                         }
1132
1133                         maxamp = compute_peak (buf, to_read, maxamp);
1134                 }
1135
1136                 fpos += to_read;
1137                 if (p) {
1138                         p->set_progress (float (fpos - _start) / _length);
1139                         if (p->cancelled ()) {
1140                                 return -1;
1141                         }
1142                 }
1143         }
1144
1145         return maxamp;
1146 }
1147
1148 /** Normalize using a given maximum amplitude and target, so that region
1149  *  _scale_amplitude becomes target / max_amplitude.
1150  */
1151 void
1152 AudioRegion::normalize (float max_amplitude, float target_dB)
1153 {
1154         gain_t target = dB_to_coefficient (target_dB);
1155
1156         if (target == 1.0f) {
1157                 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1158                    that we may have clipped.
1159                 */
1160                 target -= FLT_EPSILON;
1161         }
1162
1163         if (max_amplitude == 0.0f) {
1164                 /* don't even try */
1165                 return;
1166         }
1167
1168         if (max_amplitude == target) {
1169                 /* we can't do anything useful */
1170                 return;
1171         }
1172
1173         set_scale_amplitude (target / max_amplitude);
1174 }
1175
1176 void
1177 AudioRegion::fade_in_changed ()
1178 {
1179         send_change (PropertyChange (Properties::fade_in));
1180 }
1181
1182 void
1183 AudioRegion::fade_out_changed ()
1184 {
1185         send_change (PropertyChange (Properties::fade_out));
1186 }
1187
1188 void
1189 AudioRegion::envelope_changed ()
1190 {
1191         send_change (PropertyChange (Properties::envelope));
1192 }
1193
1194 void
1195 AudioRegion::suspend_fade_in ()
1196 {
1197         if (++_fade_in_suspended == 1) {
1198                 if (fade_in_is_default()) {
1199                         set_fade_in_active (false);
1200                 }
1201         }
1202 }
1203
1204 void
1205 AudioRegion::resume_fade_in ()
1206 {
1207         if (--_fade_in_suspended == 0 && _fade_in_suspended) {
1208                 set_fade_in_active (true);
1209         }
1210 }
1211
1212 void
1213 AudioRegion::suspend_fade_out ()
1214 {
1215         if (++_fade_out_suspended == 1) {
1216                 if (fade_out_is_default()) {
1217                         set_fade_out_active (false);
1218                 }
1219         }
1220 }
1221
1222 void
1223 AudioRegion::resume_fade_out ()
1224 {
1225         if (--_fade_out_suspended == 0 &&_fade_out_suspended) {
1226                 set_fade_out_active (true);
1227         }
1228 }
1229
1230 bool
1231 AudioRegion::speed_mismatch (float sr) const
1232 {
1233         if (_sources.empty()) {
1234                 /* impossible, but ... */
1235                 return false;
1236         }
1237
1238         float fsr = audio_source()->sample_rate();
1239
1240         return fsr != sr;
1241 }
1242
1243 void
1244 AudioRegion::source_offset_changed ()
1245 {
1246         /* XXX this fixes a crash that should not occur. It does occur
1247            becauses regions are not being deleted when a session
1248            is unloaded. That bug must be fixed.
1249         */
1250
1251         if (_sources.empty()) {
1252                 return;
1253         }
1254
1255         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(_sources.front());
1256
1257         if (afs && afs->destructive()) {
1258                 // set_start (source()->natural_position(), this);
1259                 set_position (source()->natural_position());
1260         }
1261 }
1262
1263 boost::shared_ptr<AudioSource>
1264 AudioRegion::audio_source (uint32_t n) const
1265 {
1266         // Guaranteed to succeed (use a static cast for speed?)
1267         return boost::dynamic_pointer_cast<AudioSource>(source(n));
1268 }
1269
1270 int
1271 AudioRegion::adjust_transients (frameoffset_t delta)
1272 {
1273         for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1274                 (*x) = (*x) + delta;
1275         }
1276
1277         send_change (PropertyChange (Properties::valid_transients));
1278
1279         return 0;
1280 }
1281
1282 int
1283 AudioRegion::update_transient (framepos_t old_position, framepos_t new_position)
1284 {
1285         for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1286                 if ((*x) == old_position) {
1287                         (*x) = new_position;
1288                         send_change (PropertyChange (Properties::valid_transients));
1289
1290                         break;
1291                 }
1292         }
1293
1294         return 0;
1295 }
1296
1297 void
1298 AudioRegion::add_transient (framepos_t where)
1299 {
1300         _transients.push_back(where);
1301         _valid_transients = true;
1302
1303         send_change (PropertyChange (Properties::valid_transients));
1304 }
1305
1306 void
1307 AudioRegion::remove_transient (framepos_t where)
1308 {
1309         _transients.remove(where);
1310         _valid_transients = true;
1311
1312         send_change (PropertyChange (Properties::valid_transients));
1313 }
1314
1315 int
1316 AudioRegion::set_transients (AnalysisFeatureList& results)
1317 {
1318         _transients.clear();
1319         _transients = results;
1320         _valid_transients = true;
1321
1322         send_change (PropertyChange (Properties::valid_transients));
1323
1324         return 0;
1325 }
1326
1327 int
1328 AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
1329 {
1330         boost::shared_ptr<Playlist> pl = playlist();
1331
1332         if (!pl) {
1333                 return -1;
1334         }
1335
1336         if (_valid_transients && !force_new) {
1337                 results = _transients;
1338                 return 0;
1339         }
1340
1341         SourceList::iterator s;
1342
1343         for (s = _sources.begin() ; s != _sources.end(); ++s) {
1344                 if (!(*s)->has_been_analysed()) {
1345                         cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
1346                         break;
1347                 }
1348         }
1349
1350         if (s == _sources.end()) {
1351                 /* all sources are analyzed, merge data from each one */
1352
1353                 for (s = _sources.begin() ; s != _sources.end(); ++s) {
1354
1355                         /* find the set of transients within the bounds of this region */
1356
1357                         AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
1358                                                                          (*s)->transients.end(),
1359                                                                          _start);
1360
1361                         AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
1362                                                                           (*s)->transients.end(),
1363                                                                           _start + _length);
1364
1365                         /* and add them */
1366
1367                         results.insert (results.end(), low, high);
1368                 }
1369
1370                 TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1371
1372                 /* translate all transients to current position */
1373
1374                 for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
1375                         (*x) -= _start;
1376                         (*x) += _position;
1377                 }
1378
1379                 _transients = results;
1380                 _valid_transients = true;
1381
1382                 return 0;
1383         }
1384
1385         /* no existing/complete transient info */
1386
1387         static bool analyse_dialog_shown = false; /* global per instance of Ardour */
1388
1389         if (!Config->get_auto_analyse_audio()) {
1390                 if (!analyse_dialog_shown) {
1391                         pl->session().Dialog (_("\
1392 You have requested an operation that requires audio analysis.\n\n\
1393 You currently have \"auto-analyse-audio\" disabled, which means \
1394 that transient data must be generated every time it is required.\n\n\
1395 If you are doing work that will require transient data on a \
1396 regular basis, you should probably enable \"auto-analyse-audio\" \
1397 then quit ardour and restart.\n\n\
1398 This dialog will not display again.  But you may notice a slight delay \
1399 in this and future transient-detection operations.\n\
1400 "));
1401                         analyse_dialog_shown = true;
1402                 }
1403         }
1404
1405         TransientDetector t (pl->session().frame_rate());
1406         bool existing_results = !results.empty();
1407
1408         _transients.clear ();
1409         _valid_transients = false;
1410
1411         for (uint32_t i = 0; i < n_channels(); ++i) {
1412
1413                 AnalysisFeatureList these_results;
1414
1415                 t.reset ();
1416
1417                 if (t.run ("", this, i, these_results)) {
1418                         return -1;
1419                 }
1420
1421                 /* translate all transients to give absolute position */
1422
1423                 for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
1424                         (*i) += _position;
1425                 }
1426
1427                 /* merge */
1428
1429                 _transients.insert (_transients.end(), these_results.begin(), these_results.end());
1430         }
1431
1432         if (!results.empty()) {
1433                 if (existing_results) {
1434
1435                         /* merge our transients into the existing ones, then clean up
1436                            those.
1437                         */
1438
1439                         results.insert (results.end(), _transients.begin(), _transients.end());
1440                         TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1441                 }
1442
1443                 /* make sure ours are clean too */
1444
1445                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1446
1447         } else {
1448
1449                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1450                 results = _transients;
1451         }
1452
1453         _valid_transients = true;
1454
1455         return 0;
1456 }
1457
1458 /** Find areas of `silence' within a region.
1459  *
1460  *  @param threshold Threshold below which signal is considered silence (as a sample value)
1461  *  @param min_length Minimum length of silent period to be reported.
1462  *  @return Silent intervals, measured relative to the region start in the source
1463  */
1464
1465 AudioIntervalResult
1466 AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
1467 {
1468         framecnt_t const block_size = 64 * 1024;
1469         boost::scoped_array<Sample> loudest (new Sample[block_size]);
1470         boost::scoped_array<Sample> buf (new Sample[block_size]);
1471
1472         framepos_t pos = _start;
1473         framepos_t const end = _start + _length - 1;
1474
1475         AudioIntervalResult silent_periods;
1476
1477         bool in_silence = false;
1478         frameoffset_t silence_start = 0;
1479
1480         while (pos < end && !itt.cancel) {
1481
1482                 /* fill `loudest' with the loudest absolute sample at each instant, across all channels */
1483                 memset (loudest.get(), 0, sizeof (Sample) * block_size);
1484                 for (uint32_t n = 0; n < n_channels(); ++n) {
1485
1486                         read_raw_internal (buf.get(), pos, block_size, n);
1487                         for (framecnt_t i = 0; i < block_size; ++i) {
1488                                 loudest[i] = max (loudest[i], abs (buf[i]));
1489                         }
1490                 }
1491
1492                 /* now look for silence */
1493                 for (framecnt_t i = 0; i < block_size; ++i) {
1494                         bool const silence = abs (loudest[i]) < threshold;
1495                         if (silence && !in_silence) {
1496                                 /* non-silence to silence */
1497                                 in_silence = true;
1498                                 silence_start = pos + i;
1499                         } else if (!silence && in_silence) {
1500                                 /* silence to non-silence */
1501                                 in_silence = false;
1502                                 if (pos + i - 1 - silence_start >= min_length) {
1503                                         silent_periods.push_back (std::make_pair (silence_start, pos + i - 1));
1504                                 }
1505                         }
1506                 }
1507
1508                 pos += block_size;
1509                 itt.progress = (end-pos)/(double)_length;
1510         }
1511
1512         if (in_silence && end - 1 - silence_start >= min_length) {
1513                 /* last block was silent, so finish off the last period */
1514                 silent_periods.push_back (std::make_pair (silence_start, end));
1515         }
1516
1517         itt.done = true;
1518
1519         return silent_periods;
1520 }
1521
1522
1523
1524 extern "C" {
1525
1526         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)
1527 {
1528         return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (framecnt_t) npeaks, (framepos_t) start, (framecnt_t) cnt, n_chan,samples_per_unit);
1529 }
1530
1531 uint32_t region_length_from_c (void *arg)
1532 {
1533
1534         return ((AudioRegion *) arg)->length();
1535 }
1536
1537 uint32_t sourcefile_length_from_c (void *arg, double zoom_factor)
1538 {
1539         return ( (AudioRegion *) arg)->audio_source()->available_peaks (zoom_factor) ;
1540 }
1541
1542 } /* extern "C" */