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