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