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