a68b7b1f650fe58389b741686ecd563792ffdcdf
[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, 0, 0, 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,
355                       framecnt_t read_frames, framecnt_t skip_frames) const
356 {
357         /* regular diskstream/butler read complete with fades etc */
358         return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer,
359                         file_position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
360 }
361
362 framecnt_t
363 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
364                              framepos_t position, framecnt_t cnt, uint32_t chan_n) const
365 {
366         /* do not read gain/scaling/fades and do not count this disk i/o in statistics */
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, 0, 0, ReadOps (0));
370 }
371
372 framecnt_t
373 AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit,
374                        Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
375                        framepos_t position, 
376                        framecnt_t cnt,
377                        uint32_t chan_n,
378                        framecnt_t /*read_frames*/,
379                        framecnt_t /*skip_frames*/,
380                        ReadOps rops) const
381 {
382         frameoffset_t internal_offset;
383         frameoffset_t buf_offset;
384         framecnt_t to_read;
385         bool raw = (rops == ReadOpsNone);
386
387         if (n_channels() == 0) {
388                 return 0;
389         }
390
391         if (muted() && !raw) {
392                 return 0; /* read nothing */
393         }
394
395         /* precondition: caller has verified that we cover the desired section */
396
397         if (position < _position) {
398                 internal_offset = 0;
399                 buf_offset = _position - position;
400                 cnt -= buf_offset;
401         } else {
402                 internal_offset = position - _position;
403                 buf_offset = 0;
404         }
405
406         if (internal_offset >= limit) {
407                 return 0; /* read nothing */
408         }
409
410         if ((to_read = min (cnt, limit - internal_offset)) == 0) {
411                 return 0; /* read nothing */
412         }
413
414         if (opaque() || raw) {
415                 /* overwrite whatever is there */
416                 mixdown_buffer = buf + buf_offset;
417         } else {
418                 mixdown_buffer += buf_offset;
419         }
420
421         if (rops & ReadOpsCount) {
422                 _read_data_count = 0;
423         }
424
425         if (chan_n < n_channels()) {
426
427                 boost::shared_ptr<AudioSource> src = audio_source(chan_n);
428                 if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
429                         return 0; /* "read nothing" */
430                 }
431
432                 if (rops & ReadOpsCount) {
433                         _read_data_count += src->read_data_count();
434                 }
435
436         } else {
437
438                 /* track is N-channel, this region has less channels; silence the ones
439                    we don't have.
440                 */
441
442                 if (Config->get_replicate_missing_region_channels()) {
443                         /* track is N-channel, this region has less channels, so use a relevant channel
444                          */
445                         
446                         uint32_t channel = n_channels() % chan_n;
447                         boost::shared_ptr<AudioSource> src = audio_source (channel);
448
449                         if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
450                                 return 0; /* "read nothing" */
451                         }
452
453                         /* adjust read data count appropriately since this was a duplicate read */
454                         src->dec_read_data_count (to_read);
455                 } else {
456                         memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
457                 }
458         }
459
460         if (rops & ReadOpsFades) {
461
462                 /* fade in */
463
464                 if (_fade_in_active && _session.config.get_use_region_fades()) {
465
466                         framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
467
468                         /* see if this read is within the fade in */
469
470                         if (internal_offset < fade_in_length) {
471
472                                 framecnt_t fi_limit;
473
474                                 fi_limit = min (to_read, fade_in_length - internal_offset);
475
476                                 _fade_in->curve().get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit);
477
478                                 for (framecnt_t n = 0; n < fi_limit; ++n) {
479                                         mixdown_buffer[n] *= gain_buffer[n];
480                                 }
481                         }
482                 }
483
484                 /* fade out */
485
486                 if (_fade_out_active && _session.config.get_use_region_fades()) {
487
488                         /* see if some part of this read is within the fade out */
489
490                 /* .................        >|            REGION
491                                              limit
492
493                                  {           }            FADE
494                                              fade_out_length
495                                  ^
496                                  limit - fade_out_length
497                         |--------------|
498                         ^internal_offset
499                                        ^internal_offset + to_read
500
501                                        we need the intersection of [internal_offset,internal_offset+to_read] with
502                                        [limit - fade_out_length, limit]
503
504                 */
505
506
507                         framecnt_t fade_out_length     = (framecnt_t) _fade_out->back()->when;
508                         framecnt_t fade_interval_start = max(internal_offset, limit-fade_out_length);
509                         framecnt_t fade_interval_end   = min(internal_offset + to_read, limit);
510
511                         if (fade_interval_end > fade_interval_start) {
512                                 /* (part of the) the fade out is  in this buffer */
513
514                                 framecnt_t fo_limit = fade_interval_end - fade_interval_start;
515                                 framecnt_t curve_offset = fade_interval_start - (limit-fade_out_length);
516                                 framecnt_t fade_offset = fade_interval_start - internal_offset;
517
518                                 _fade_out->curve().get_vector (curve_offset, curve_offset+fo_limit, gain_buffer, fo_limit);
519
520                                 for (framecnt_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) {
521                                         mixdown_buffer[m] *= gain_buffer[n];
522                                 }
523                         }
524
525                 }
526         }
527
528         /* Regular gain curves and scaling */
529
530         if ((rops & ReadOpsOwnAutomation) && envelope_active())  {
531                 _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
532
533                 if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
534                         for (framecnt_t n = 0; n < to_read; ++n) {
535                                 mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
536                         }
537                 } else {
538                         for (framecnt_t n = 0; n < to_read; ++n) {
539                                 mixdown_buffer[n] *= gain_buffer[n];
540                         }
541                 }
542         } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
543
544                 // XXX this should be using what in 2.0 would have been:
545                 // Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
546
547                 for (framecnt_t n = 0; n < to_read; ++n) {
548                         mixdown_buffer[n] *= _scale_amplitude;
549                 }
550         }
551
552         if (!opaque() && (buf != mixdown_buffer)) {
553
554                 /* gack. the things we do for users.
555                  */
556
557                 buf += buf_offset;
558
559                 for (framecnt_t n = 0; n < to_read; ++n) {
560                         buf[n] += mixdown_buffer[n];
561                 }
562         }
563
564         return to_read;
565 }
566
567 XMLNode&
568 AudioRegion::state ()
569 {
570         XMLNode& node (Region::state ());
571         XMLNode *child;
572         char buf[64];
573         LocaleGuard lg (X_("POSIX"));
574
575         snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
576         node.add_property ("channels", buf);
577
578         Stateful::add_properties (node);
579
580         child = node.add_child ("Envelope");
581
582         bool default_env = false;
583         
584         // If there are only two points, the points are in the start of the region and the end of the region
585         // so, if they are both at 1.0f, that means the default region.
586         
587         if (_envelope->size() == 2 &&
588             _envelope->front()->value == 1.0f &&
589             _envelope->back()->value==1.0f) {
590                 if (_envelope->front()->when == 0 && _envelope->back()->when == _length) {
591                         default_env = true;
592                 }
593         }
594         
595         if (default_env) {
596                 child->add_property ("default", "yes");
597         } else {
598                 child->add_child_nocopy (_envelope->get_state ());
599         }
600
601         child = node.add_child (X_("FadeIn"));
602
603         if (_default_fade_in) {
604                 child->add_property ("default", "yes");
605         } else {
606                 child->add_child_nocopy (_fade_in->get_state ());
607         }
608
609         child = node.add_child (X_("FadeOut"));
610
611         if (_default_fade_out) {
612                 child->add_property ("default", "yes");
613         } else {
614                 child->add_child_nocopy (_fade_out->get_state ());
615         }
616
617         return node;
618 }
619
620 int
621 AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_changed, bool send)
622 {
623         const XMLNodeList& nlist = node.children();
624         const XMLProperty *prop;
625         LocaleGuard lg (X_("POSIX"));
626         boost::shared_ptr<Playlist> the_playlist (_playlist.lock());    
627
628         suspend_property_changes ();
629
630         if (the_playlist) {
631                 the_playlist->freeze ();
632         }
633
634
635         /* this will set all our State members and stuff controlled by the Region.
636            It should NOT send any changed signals - that is our responsibility.
637         */
638
639         Region::_set_state (node, version, what_changed, false);
640
641         if ((prop = node.property ("scale-gain")) != 0) {
642                 float a = atof (prop->value().c_str());
643                 if (a != _scale_amplitude) {
644                         _scale_amplitude = a;
645                         what_changed.add (Properties::scale_amplitude);
646                 }
647         }
648
649         /* Now find envelope description and other related child items */
650
651         _envelope->freeze ();
652
653         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
654                 XMLNode *child;
655                 XMLProperty *prop;
656
657                 child = (*niter);
658
659                 if (child->name() == "Envelope") {
660
661                         _envelope->clear ();
662
663                         if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child, version)) {
664                                 set_default_envelope ();
665                         }
666
667                         _envelope->set_max_xval (_length);
668                         _envelope->truncate_end (_length);
669
670
671                 } else if (child->name() == "FadeIn") {
672
673                         _fade_in->clear ();
674
675                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
676                                 set_default_fade_in ();
677                         } else {
678                                 XMLNode* grandchild = child->child ("AutomationList");
679                                 if (grandchild) {
680                                         _fade_in->set_state (*grandchild, version);
681                                 }
682                         }
683
684                         if ((prop = child->property ("active")) != 0) {
685                                 if (string_is_affirmative (prop->value())) {
686                                         set_fade_in_active (true);
687                                 } else {
688                                         set_fade_in_active (false);
689                                 }
690                         }
691
692                 } else if (child->name() == "FadeOut") {
693
694                         _fade_out->clear ();
695
696                         if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
697                                 set_default_fade_out ();
698                         } else {
699                                 XMLNode* grandchild = child->child ("AutomationList");
700                                 if (grandchild) {
701                                         _fade_out->set_state (*grandchild, version);
702                                 }
703                         }
704
705                         if ((prop = child->property ("active")) != 0) {
706                                 if (string_is_affirmative (prop->value())) {
707                                         set_fade_out_active (true);
708                                 } else {
709                                         set_fade_out_active (false);
710                                 }
711                         }
712
713                 }
714         }
715
716         _envelope->thaw ();
717         resume_property_changes ();
718
719         if (send) {
720                 send_change (what_changed);
721         }
722
723         if (the_playlist) {
724                 the_playlist->thaw ();
725         }
726
727         return 0;
728 }
729
730 int
731 AudioRegion::set_state (const XMLNode& node, int version)
732 {
733         PropertyChange what_changed;
734         return _set_state (node, version, what_changed, true);
735 }
736
737 void
738 AudioRegion::set_fade_in_shape (FadeShape shape)
739 {
740         set_fade_in (shape, (framecnt_t) _fade_in->back()->when);
741 }
742
743 void
744 AudioRegion::set_fade_out_shape (FadeShape shape)
745 {
746         set_fade_out (shape, (framecnt_t) _fade_out->back()->when);
747 }
748
749 void
750 AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
751 {
752         _fade_in->freeze ();
753         *_fade_in = *f;
754         _fade_in->thaw ();
755         
756         send_change (PropertyChange (Properties::fade_in));
757 }
758
759 void
760 AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
761 {
762         _fade_in->freeze ();
763         _fade_in->clear ();
764
765         switch (shape) {
766         case FadeLinear:
767                 _fade_in->fast_simple_add (0.0, 0.0);
768                 _fade_in->fast_simple_add (len, 1.0);
769                 break;
770
771         case FadeFast:
772                 _fade_in->fast_simple_add (0, 0);
773                 _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
774                 _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
775                 _fade_in->fast_simple_add (len * 0.829493, 0.233333);
776                 _fade_in->fast_simple_add (len * 0.9447, 0.483333);
777                 _fade_in->fast_simple_add (len * 0.976959, 0.697222);
778                 _fade_in->fast_simple_add (len, 1);
779                 break;
780
781         case FadeSlow:
782                 _fade_in->fast_simple_add (0, 0);
783                 _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
784                 _fade_in->fast_simple_add (len * 0.0645161, 0.525);
785                 _fade_in->fast_simple_add (len * 0.152074, 0.802778);
786                 _fade_in->fast_simple_add (len * 0.276498, 0.919444);
787                 _fade_in->fast_simple_add (len * 0.481567, 0.980556);
788                 _fade_in->fast_simple_add (len * 0.767281, 1);
789                 _fade_in->fast_simple_add (len, 1);
790                 break;
791
792         case FadeLogA:
793                 _fade_in->fast_simple_add (0, 0);
794                 _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
795                 _fade_in->fast_simple_add (len * 0.246544, 0.658333);
796                 _fade_in->fast_simple_add (len * 0.470046, 0.886111);
797                 _fade_in->fast_simple_add (len * 0.652074, 0.972222);
798                 _fade_in->fast_simple_add (len * 0.771889, 0.988889);
799                 _fade_in->fast_simple_add (len, 1);
800                 break;
801
802         case FadeLogB:
803                 _fade_in->fast_simple_add (0, 0);
804                 _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
805                 _fade_in->fast_simple_add (len * 0.529954, 0.152778);
806                 _fade_in->fast_simple_add (len * 0.725806, 0.333333);
807                 _fade_in->fast_simple_add (len * 0.847926, 0.558333);
808                 _fade_in->fast_simple_add (len * 0.919355, 0.730556);
809                 _fade_in->fast_simple_add (len, 1);
810                 break;
811         }
812
813         _fade_in->thaw ();
814         send_change (PropertyChange (Properties::fade_in));
815 }
816
817 void
818 AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
819 {
820         _fade_out->freeze ();
821         *_fade_out = *f;
822         _fade_out->thaw ();
823
824         send_change (PropertyChange (Properties::fade_in));
825 }
826
827 void
828 AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
829 {
830         _fade_out->freeze ();
831         _fade_out->clear ();
832
833         switch (shape) {
834         case FadeFast:
835                 _fade_out->fast_simple_add (len * 0, 1);
836                 _fade_out->fast_simple_add (len * 0.023041, 0.697222);
837                 _fade_out->fast_simple_add (len * 0.0553,   0.483333);
838                 _fade_out->fast_simple_add (len * 0.170507, 0.233333);
839                 _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
840                 _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
841                 _fade_out->fast_simple_add (len * 1, 0);
842                 break;
843
844         case FadeLogA:
845                 _fade_out->fast_simple_add (len * 0, 1);
846                 _fade_out->fast_simple_add (len * 0.228111, 0.988889);
847                 _fade_out->fast_simple_add (len * 0.347926, 0.972222);
848                 _fade_out->fast_simple_add (len * 0.529954, 0.886111);
849                 _fade_out->fast_simple_add (len * 0.753456, 0.658333);
850                 _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
851                 _fade_out->fast_simple_add (len * 1, 0);
852                 break;
853
854         case FadeSlow:
855                 _fade_out->fast_simple_add (len * 0, 1);
856                 _fade_out->fast_simple_add (len * 0.305556, 1);
857                 _fade_out->fast_simple_add (len * 0.548611, 0.991736);
858                 _fade_out->fast_simple_add (len * 0.759259, 0.931129);
859                 _fade_out->fast_simple_add (len * 0.918981, 0.68595);
860                 _fade_out->fast_simple_add (len * 0.976852, 0.22865);
861                 _fade_out->fast_simple_add (len * 1, 0);
862                 break;
863
864         case FadeLogB:
865                 _fade_out->fast_simple_add (len * 0, 1);
866                 _fade_out->fast_simple_add (len * 0.080645, 0.730556);
867                 _fade_out->fast_simple_add (len * 0.277778, 0.289256);
868                 _fade_out->fast_simple_add (len * 0.470046, 0.152778);
869                 _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
870                 _fade_out->fast_simple_add (len * 1, 0);
871                 break;
872
873         case FadeLinear:
874                 _fade_out->fast_simple_add (len * 0, 1);
875                 _fade_out->fast_simple_add (len * 1, 0);
876                 break;
877         }
878
879         _fade_out->thaw ();
880         send_change (PropertyChange (Properties::fade_in));
881 }
882
883 void
884 AudioRegion::set_fade_in_length (framecnt_t len)
885 {
886         if (len > _length) {
887                 len = _length - 1;
888         }
889
890         bool changed = _fade_in->extend_to (len);
891
892         if (changed) {
893                 _default_fade_in = false;
894                 send_change (PropertyChange (Properties::fade_in));
895         }
896 }
897
898 void
899 AudioRegion::set_fade_out_length (framecnt_t len)
900 {
901         if (len > _length) {
902                 len = _length - 1;
903         }
904
905         bool changed =  _fade_out->extend_to (len);
906
907         if (changed) {
908                 _default_fade_out = false;
909                 send_change (PropertyChange (Properties::fade_out));
910         }
911 }
912
913 void
914 AudioRegion::set_fade_in_active (bool yn)
915 {
916         if (yn == _fade_in_active) {
917                 return;
918         }
919
920         _fade_in_active = yn;
921         send_change (PropertyChange (Properties::fade_in_active));
922 }
923
924 void
925 AudioRegion::set_fade_out_active (bool yn)
926 {
927         if (yn == _fade_out_active) {
928                 return;
929         }
930         _fade_out_active = yn;
931         send_change (PropertyChange (Properties::fade_out_active));
932 }
933
934 bool
935 AudioRegion::fade_in_is_default () const
936 {
937         return _fade_in->size() == 2 && _fade_in->front()->when == 0 && _fade_in->back()->when == 64;
938 }
939
940 bool
941 AudioRegion::fade_out_is_default () const
942 {
943         return _fade_out->size() == 2 && _fade_out->front()->when == 0 && _fade_out->back()->when == 64;
944 }
945
946 void
947 AudioRegion::set_default_fade_in ()
948 {
949         _fade_in_suspended = 0;
950         set_fade_in (FadeLinear, 64);
951 }
952
953 void
954 AudioRegion::set_default_fade_out ()
955 {
956         _fade_out_suspended = 0;
957         set_fade_out (FadeLinear, 64);
958 }
959
960 void
961 AudioRegion::set_default_fades ()
962 {
963         set_default_fade_in ();
964         set_default_fade_out ();
965 }
966
967 void
968 AudioRegion::set_default_envelope ()
969 {
970         _envelope->freeze ();
971         _envelope->clear ();
972         _envelope->fast_simple_add (0, 1.0f);
973         _envelope->fast_simple_add (_length, 1.0f);
974         _envelope->thaw ();
975 }
976
977 void
978 AudioRegion::recompute_at_end ()
979 {
980         /* our length has changed. recompute a new final point by interpolating
981            based on the the existing curve.
982         */
983
984         _envelope->freeze ();
985         _envelope->truncate_end (_length);
986         _envelope->set_max_xval (_length);
987         _envelope->thaw ();
988         
989         suspend_property_changes();
990
991         if (_left_of_split) {
992                 set_default_fade_out ();
993                 _left_of_split = false;
994         } else if (_fade_out->back()->when > _length) {
995                 _fade_out->extend_to (_length);
996                 send_change (PropertyChange (Properties::fade_out));
997         }
998
999         if (_fade_in->back()->when > _length) {
1000                 _fade_in->extend_to (_length);
1001                 send_change (PropertyChange (Properties::fade_in));
1002         }
1003         
1004         resume_property_changes();
1005 }
1006
1007 void
1008 AudioRegion::recompute_at_start ()
1009 {
1010         /* as above, but the shift was from the front */
1011
1012         _envelope->truncate_start (_length);
1013         
1014         suspend_property_changes();
1015
1016         if (_right_of_split) {
1017                 set_default_fade_in ();
1018                 _right_of_split = false;
1019         } else if (_fade_in->back()->when > _length) {
1020                 _fade_in->extend_to (_length);
1021                 send_change (PropertyChange (Properties::fade_in));
1022         }
1023
1024         if (_fade_out->back()->when > _length) {
1025                 _fade_out->extend_to (_length);
1026                 send_change (PropertyChange (Properties::fade_out));
1027         }
1028         
1029         resume_property_changes();
1030 }
1031
1032 int
1033 AudioRegion::separate_by_channel (Session& /*session*/, vector<boost::shared_ptr<Region> >& v) const
1034 {
1035         SourceList srcs;
1036         string new_name;
1037         int n = 0;
1038
1039         if (_sources.size() < 2) {
1040                 return 0;
1041         }
1042
1043         for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
1044                 srcs.clear ();
1045                 srcs.push_back (*i);
1046
1047                 new_name = _name;
1048
1049                 if (_sources.size() == 2) {
1050                         if (n == 0) {
1051                                 new_name += "-L";
1052                         } else {
1053                                 new_name += "-R";
1054                         }
1055                 } else {
1056                         new_name += '-';
1057                         new_name += ('0' + n + 1);
1058                 }
1059
1060                 /* create a copy with just one source. prevent if from being thought of as
1061                    "whole file" even if it covers the entire source file(s).
1062                  */
1063
1064                 PropertyList plist;
1065                 
1066                 plist.add (Properties::start, _start.val());
1067                 plist.add (Properties::length, _length.val());
1068                 plist.add (Properties::name, new_name);
1069                 plist.add (Properties::layer, _layer.val());
1070
1071                 v.push_back(RegionFactory::create (srcs, plist));
1072                 v.back()->set_whole_file (false);
1073
1074                 ++n;
1075         }
1076
1077         return 0;
1078 }
1079
1080 framecnt_t
1081 AudioRegion::read_raw_internal (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
1082 {
1083         return audio_source(channel)->read (buf, pos, cnt);
1084 }
1085
1086 int
1087 AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec*/)
1088 {
1089         // TODO EXPORT
1090 //      const framecnt_t blocksize = 4096;
1091 //      framecnt_t to_read;
1092 //      int status = -1;
1093 //
1094 //      spec.channels = _sources.size();
1095 //
1096 //      if (spec.prepare (blocksize, session.frame_rate())) {
1097 //              goto out;
1098 //      }
1099 //
1100 //      spec.pos = 0;
1101 //      spec.total_frames = _length;
1102 //
1103 //      while (spec.pos < _length && !spec.stop) {
1104 //
1105 //
1106 //              /* step 1: interleave */
1107 //
1108 //              to_read = min (_length - spec.pos, blocksize);
1109 //
1110 //              if (spec.channels == 1) {
1111 //
1112 //                      if (read_raw_internal (spec.dataF, _start + spec.pos, to_read) != to_read) {
1113 //                              goto out;
1114 //                      }
1115 //
1116 //              } else {
1117 //
1118 //                      Sample buf[blocksize];
1119 //
1120 //                      for (uint32_t chan = 0; chan < spec.channels; ++chan) {
1121 //
1122 //                              if (audio_source(chan)->read (buf, _start + spec.pos, to_read) != to_read) {
1123 //                                      goto out;
1124 //                              }
1125 //
1126 //                              for (framecnt_t x = 0; x < to_read; ++x) {
1127 //                                      spec.dataF[chan+(x*spec.channels)] = buf[x];
1128 //                              }
1129 //                      }
1130 //              }
1131 //
1132 //              if (spec.process (to_read)) {
1133 //                      goto out;
1134 //              }
1135 //
1136 //              spec.pos += to_read;
1137 //              spec.progress = (double) spec.pos /_length;
1138 //
1139 //      }
1140 //
1141 //      status = 0;
1142 //
1143 //  out:
1144 //      spec.running = false;
1145 //      spec.status = status;
1146 //      spec.clear();
1147 //
1148 //      return status;
1149         return 0;
1150 }
1151
1152 void
1153 AudioRegion::set_scale_amplitude (gain_t g)
1154 {
1155         boost::shared_ptr<Playlist> pl (playlist());
1156
1157         _scale_amplitude = g;
1158
1159         /* tell the diskstream we're in */
1160
1161         if (pl) {
1162                 pl->ContentsChanged();
1163         }
1164
1165         /* tell everybody else */
1166
1167         send_change (PropertyChange (Properties::scale_amplitude));
1168 }
1169
1170 /** @return the maximum (linear) amplitude of the region, or a -ve
1171  *  number if the Progress object reports that the process was cancelled.
1172  */
1173 double
1174 AudioRegion::maximum_amplitude (Progress* p) const
1175 {
1176         framepos_t fpos = _start;
1177         framepos_t const fend = _start + _length;
1178         double maxamp = 0;
1179
1180         framecnt_t const blocksize = 64 * 1024;
1181         Sample buf[blocksize];
1182         
1183         while (fpos < fend) {
1184
1185                 uint32_t n;
1186
1187                 framecnt_t const to_read = min (fend - fpos, blocksize);
1188
1189                 for (n = 0; n < n_channels(); ++n) {
1190
1191                         /* read it in */
1192
1193                         if (read_raw_internal (buf, fpos, to_read, n) != to_read) {
1194                                 return 0;
1195                         }
1196
1197                         maxamp = compute_peak (buf, to_read, maxamp);
1198                 }
1199
1200                 fpos += to_read;
1201                 if (p) {
1202                         p->set_progress (float (fpos - _start) / _length);
1203                         if (p->cancelled ()) {
1204                                 return -1;
1205                         }
1206                 }
1207         }
1208
1209         return maxamp;
1210 }
1211
1212 /** Normalize using a given maximum amplitude and target, so that region
1213  *  _scale_amplitude becomes target / max_amplitude.
1214  */
1215 void
1216 AudioRegion::normalize (float max_amplitude, float target_dB)
1217 {
1218         gain_t target = dB_to_coefficient (target_dB);
1219
1220         if (target == 1.0f) {
1221                 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
1222                    that we may have clipped.
1223                 */
1224                 target -= FLT_EPSILON;
1225         }
1226
1227         if (max_amplitude == 0.0f) {
1228                 /* don't even try */
1229                 return;
1230         }
1231
1232         if (max_amplitude == target) {
1233                 /* we can't do anything useful */
1234                 return;
1235         }
1236
1237         set_scale_amplitude (target / max_amplitude);
1238 }
1239
1240 void
1241 AudioRegion::fade_in_changed ()
1242 {
1243         send_change (PropertyChange (Properties::fade_in));
1244 }
1245
1246 void
1247 AudioRegion::fade_out_changed ()
1248 {
1249         send_change (PropertyChange (Properties::fade_out));
1250 }
1251
1252 void
1253 AudioRegion::envelope_changed ()
1254 {
1255         send_change (PropertyChange (Properties::envelope));
1256 }
1257
1258 void
1259 AudioRegion::suspend_fade_in ()
1260 {
1261         if (++_fade_in_suspended == 1) {
1262                 if (fade_in_is_default()) {
1263                         set_fade_in_active (false);
1264                 }
1265         }
1266 }
1267
1268 void
1269 AudioRegion::resume_fade_in ()
1270 {
1271         if (--_fade_in_suspended == 0 && _fade_in_suspended) {
1272                 set_fade_in_active (true);
1273         }
1274 }
1275
1276 void
1277 AudioRegion::suspend_fade_out ()
1278 {
1279         if (++_fade_out_suspended == 1) {
1280                 if (fade_out_is_default()) {
1281                         set_fade_out_active (false);
1282                 }
1283         }
1284 }
1285
1286 void
1287 AudioRegion::resume_fade_out ()
1288 {
1289         if (--_fade_out_suspended == 0 &&_fade_out_suspended) {
1290                 set_fade_out_active (true);
1291         }
1292 }
1293
1294 bool
1295 AudioRegion::speed_mismatch (float sr) const
1296 {
1297         if (_sources.empty()) {
1298                 /* impossible, but ... */
1299                 return false;
1300         }
1301
1302         float fsr = audio_source()->sample_rate();
1303
1304         return fsr != sr;
1305 }
1306
1307 void
1308 AudioRegion::source_offset_changed ()
1309 {
1310         /* XXX this fixes a crash that should not occur. It does occur
1311            becauses regions are not being deleted when a session
1312            is unloaded. That bug must be fixed.
1313         */
1314
1315         if (_sources.empty()) {
1316                 return;
1317         }
1318
1319         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(_sources.front());
1320
1321         if (afs && afs->destructive()) {
1322                 // set_start (source()->natural_position(), this);
1323                 set_position (source()->natural_position());
1324         }
1325 }
1326
1327 boost::shared_ptr<AudioSource>
1328 AudioRegion::audio_source (uint32_t n) const
1329 {
1330         // Guaranteed to succeed (use a static cast for speed?)
1331         return boost::dynamic_pointer_cast<AudioSource>(source(n));
1332 }
1333
1334 int 
1335 AudioRegion::adjust_transients (frameoffset_t delta)
1336 {
1337         for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1338                 (*x) = (*x) + delta;
1339         }
1340         
1341         send_change (PropertyChange (Properties::valid_transients));
1342         
1343         return 0;  
1344
1345
1346 int
1347 AudioRegion::update_transient (framepos_t old_position, framepos_t new_position)
1348 {
1349         for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) {
1350                 if ((*x) == old_position) {
1351                         (*x) = new_position;
1352                         send_change (PropertyChange (Properties::valid_transients));
1353                         
1354                         break;
1355                 }
1356         }
1357         
1358         return 0;
1359 }
1360
1361 void
1362 AudioRegion::add_transient (framepos_t where)
1363 {
1364         _transients.push_back(where);
1365         _valid_transients = true;
1366         
1367         send_change (PropertyChange (Properties::valid_transients));
1368 }
1369
1370 void
1371 AudioRegion::remove_transient (framepos_t where)
1372 {
1373         _transients.remove(where);
1374         _valid_transients = true;
1375         
1376         send_change (PropertyChange (Properties::valid_transients));
1377 }
1378
1379 int
1380 AudioRegion::set_transients (AnalysisFeatureList& results)
1381 {
1382         _transients.clear();
1383         _transients = results;
1384         _valid_transients = true;
1385         
1386         send_change (PropertyChange (Properties::valid_transients));
1387         
1388         return 0;
1389 }
1390
1391 int
1392 AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
1393 {
1394         boost::shared_ptr<Playlist> pl = playlist();
1395
1396         if (!pl) {
1397                 return -1;
1398         }
1399
1400         if (_valid_transients && !force_new) {
1401                 results = _transients;
1402                 return 0;
1403         }
1404
1405         SourceList::iterator s;
1406
1407         for (s = _sources.begin() ; s != _sources.end(); ++s) {
1408                 if (!(*s)->has_been_analysed()) {
1409                         cerr << "For " << name() << " source " << (*s)->name() << " has not been analyzed\n";
1410                         break;
1411                 }
1412         }
1413
1414         if (s == _sources.end()) {
1415                 /* all sources are analyzed, merge data from each one */
1416
1417                 for (s = _sources.begin() ; s != _sources.end(); ++s) {
1418
1419                         /* find the set of transients within the bounds of this region */
1420
1421                         AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(),
1422                                                                          (*s)->transients.end(),
1423                                                                          _start);
1424
1425                         AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(),
1426                                                                           (*s)->transients.end(),
1427                                                                           _start + _length);
1428
1429                         /* and add them */
1430
1431                         results.insert (results.end(), low, high);
1432                 }
1433
1434                 TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1435
1436                 /* translate all transients to current position */
1437
1438                 for (AnalysisFeatureList::iterator x = results.begin(); x != results.end(); ++x) {
1439                         (*x) -= _start;
1440                         (*x) += _position;
1441                 }
1442
1443                 _transients = results;
1444                 _valid_transients = true;
1445
1446                 return 0;
1447         }
1448
1449         /* no existing/complete transient info */
1450
1451         static bool analyse_dialog_shown = false; /* global per instance of Ardour */
1452
1453         if (!Config->get_auto_analyse_audio()) {
1454                 if (!analyse_dialog_shown) {
1455                         pl->session().Dialog (_("\
1456 You have requested an operation that requires audio analysis.\n\n\
1457 You currently have \"auto-analyse-audio\" disabled, which means \
1458 that transient data must be generated every time it is required.\n\n\
1459 If you are doing work that will require transient data on a \
1460 regular basis, you should probably enable \"auto-analyse-audio\" \
1461 then quit ardour and restart.\n\n\
1462 This dialog will not display again.  But you may notice a slight delay \
1463 in this and future transient-detection operations.\n\
1464 "));
1465                         analyse_dialog_shown = true;
1466                 }
1467         }
1468
1469         TransientDetector t (pl->session().frame_rate());
1470         bool existing_results = !results.empty();
1471
1472         _transients.clear ();
1473         _valid_transients = false;
1474
1475         for (uint32_t i = 0; i < n_channels(); ++i) {
1476
1477                 AnalysisFeatureList these_results;
1478
1479                 t.reset ();
1480
1481                 if (t.run ("", this, i, these_results)) {
1482                         return -1;
1483                 }
1484
1485                 /* translate all transients to give absolute position */
1486
1487                 for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {
1488                         (*i) += _position;
1489                 }
1490
1491                 /* merge */
1492
1493                 _transients.insert (_transients.end(), these_results.begin(), these_results.end());
1494         }
1495
1496         if (!results.empty()) {
1497                 if (existing_results) {
1498
1499                         /* merge our transients into the existing ones, then clean up
1500                            those.
1501                         */
1502
1503                         results.insert (results.end(), _transients.begin(), _transients.end());
1504                         TransientDetector::cleanup_transients (results, pl->session().frame_rate(), 3.0);
1505                 }
1506
1507                 /* make sure ours are clean too */
1508
1509                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1510
1511         } else {
1512
1513                 TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0);
1514                 results = _transients;
1515         }
1516
1517         _valid_transients = true;
1518
1519         return 0;
1520 }
1521
1522 /** Find areas of `silence' within a region.
1523  *
1524  *  @param threshold Threshold below which signal is considered silence (as a sample value)
1525  *  @param min_length Minimum length of silent period to be reported.
1526  *  @return Silent intervals, measured relative to the region start in the source
1527  */
1528
1529 AudioIntervalResult
1530 AudioRegion::find_silence (Sample threshold, framecnt_t min_length, InterThreadInfo& itt) const
1531 {
1532         framecnt_t const block_size = 64 * 1024;
1533         boost::scoped_array<Sample> loudest (new Sample[block_size]);
1534         boost::scoped_array<Sample> buf (new Sample[block_size]);
1535
1536         framepos_t pos = _start;
1537         framepos_t const end = _start + _length - 1;
1538
1539         AudioIntervalResult silent_periods;
1540
1541         bool in_silence = false;
1542         frameoffset_t silence_start = 0;
1543
1544         while (pos < end && !itt.cancel) {
1545
1546                 /* fill `loudest' with the loudest absolute sample at each instant, across all channels */
1547                 memset (loudest.get(), 0, sizeof (Sample) * block_size);
1548                 for (uint32_t n = 0; n < n_channels(); ++n) {
1549
1550                         read_raw_internal (buf.get(), pos, block_size, n);
1551                         for (framecnt_t i = 0; i < block_size; ++i) {
1552                                 loudest[i] = max (loudest[i], abs (buf[i]));
1553                         }
1554                 }
1555
1556                 /* now look for silence */
1557                 for (framecnt_t i = 0; i < block_size; ++i) {
1558                         bool const silence = abs (loudest[i]) < threshold;
1559                         if (silence && !in_silence) {
1560                                 /* non-silence to silence */
1561                                 in_silence = true;
1562                                 silence_start = pos + i;
1563                         } else if (!silence && in_silence) {
1564                                 /* silence to non-silence */
1565                                 in_silence = false;
1566                                 if (pos + i - 1 - silence_start >= min_length) {
1567                                         silent_periods.push_back (std::make_pair (silence_start, pos + i - 1));
1568                                 }
1569                         }
1570                 }
1571
1572                 pos += block_size;
1573                 itt.progress = (end-pos)/(double)_length;
1574         }
1575
1576         if (in_silence && end - 1 - silence_start >= min_length) {
1577                 /* last block was silent, so finish off the last period */
1578                 silent_periods.push_back (std::make_pair (silence_start, end));
1579         }
1580
1581         itt.done = true;
1582
1583         return silent_periods;
1584 }
1585
1586
1587
1588 extern "C" {
1589
1590         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)
1591 {
1592         return ((AudioRegion *) arg)->read_peaks ((PeakData *) data, (framecnt_t) npeaks, (framepos_t) start, (framecnt_t) cnt, n_chan,samples_per_unit);
1593 }
1594
1595 uint32_t region_length_from_c (void *arg)
1596 {
1597
1598         return ((AudioRegion *) arg)->length();
1599 }
1600
1601 uint32_t sourcefile_length_from_c (void *arg, double zoom_factor)
1602 {
1603         return ( (AudioRegion *) arg)->audio_source()->available_peaks (zoom_factor) ;
1604 }
1605
1606 } /* extern "C" */