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