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