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